home *** CD-ROM | disk | FTP | other *** search
/ No Fragments Archive 12: Textmags & Docs / nf_archive_12.iso / MAGS / SOURCES / ATARI_SRC.ZIP / atari source / AHDI / TTDRIVER / 4.02 / DRIVER.S < prev    next >
Encoding:
Text File  |  2001-02-09  |  65.7 KB  |  2,131 lines

  1. ; Dec 06 1990 v4.02'
  2.  
  3. ;------------------------------------------------------------------------
  4. ;                                    :
  5. ;    AHDI Hard Disk Driver for the Atari ST and TT            :
  6. ;    Copyright 1985,1986,1987,1988,1989,1990 Atari Corp.        :
  7. ;    All Rights Reserved                        :
  8. ;                                    :
  9. ;------------------------------------------------------------------------
  10.  
  11.  
  12. ;+
  13. ; Conditional Assembly Switches
  14. ;-
  15. ospool        equ    1        ; increase size of OS pool for ROM
  16.  
  17.  
  18. ;
  19. ;+
  20. ; Edit History
  21. ;
  22. ;
  23. ; 22-May-1989    ml    Started this from ahdi 3.00
  24. ;            Files created for this driver:
  25. ;            ACSI.S        Low-level driver for ACSI.
  26. ;            CMDBLK.S    Builds packets for command blocks.
  27. ;            DOIT.S        Sends packets out to SCSI or ACSI.
  28. ;            DRIVER.S    This file.
  29. ;            SCSI.S        Low-level driver for SCSI.
  30. ;
  31. ; 25-May-1989    ml    Eliminated pread(), use _ahdi_rw() in physical mode
  32. ;            instead.
  33. ;
  34. ; 06-Jun-1989    ml    Created INSTALL.S for driver installation.
  35. ;
  36. ; 11-Jul-1989    ml    Rwabs() now handles DMA to fast RAM on ACSI side
  37. ;            also.  If no extra RAM was reserved for fast RAM
  38. ;            transferred, _dskbufp is used for the transfer.
  39. ;            (This is going to be really slow!!!)
  40. ;
  41. ; 19-Jul-1989    ml    If there is cache on CPU, Rwabs() reads will
  42. ;            flush both the I and D cache.
  43. ;
  44. ; 06-Sept-1989    ml    Use _FRB (in the cookie jar) for fast RAM transfer,
  45. ;            assuming _FRB WILL be there if there is fast RAM on
  46. ;            the machine.
  47. ;
  48. ; 20-Feb-1990    ml 3.64    Fixed bug in return code when doing ACSI odd transfer.
  49. ;            When successful, 0 should be returned.
  50. ;
  51. ; 02-Mar-1990    ml 3.65    Took out wait loop for SCSI 0 to be ready.
  52. ;            (In install.s)
  53. ;
  54. ; 05-Mar-1990    ml 3.66    Added more checks for I/O to ACSI and SCSI non-
  55. ;            accessible memory.  _FRB will be used if it exists.
  56. ;            If _FRB doesn't exist, _dskbuf will used (which
  57. ;            means I/O could be "really" slow).  (_do_rw())
  58. ;
  59. ;            _FRB is being looked for when it's needed for the
  60. ;            first time, not at boot time.  (Applications can
  61. ;            add the _FRB when they are executed.)
  62. ;
  63. ; 08-Mar-1990    ml    Added SCFRDMA flag in defs.h to make SCSI DMA to 
  64. ;            fast RAM conditional assembly.
  65. ;            (driver.s modified)
  66. ;
  67. ; 15-Mar-1990    ml    Added DEBUG flag in defs.h to make debugging code
  68. ;            conditional assembly.
  69. ;
  70. ; 09-Apr-1990    ml 3.67    Added a "read" from WDL after toggling the ACSI DMA
  71. ;            chip to point the MMU to the correct direction.
  72. ;            (In acsi.s)
  73. ;
  74. ; 10-Apr-1990    ml    Put up banner at beginning and end of loading driver
  75. ;            (requested by jwt), instead of just at the end.
  76. ;            (Printing of banner moved to install.s)
  77. ;
  78. ; 17-Apr-1990    ml    Added ODMA flag in defs.h to make the klutch of 
  79. ;            making byte counter bigger than # bytes requested
  80. ;            when receiving data from SCSI conditional assembly.
  81. ;            (scsi.s modified)
  82. ;
  83. ; 20-Apr-1990    ml    Added RDWDL flag in defs.h to make the "extra read"
  84. ;            added on 09-Apr-1990 conditional assembly.  (When
  85. ;            writing to ACSI, first 32 bytes are always FF's!!
  86. ;            Wondering why...)
  87. ;            (acsi.s modified)
  88. ;
  89. ; 30-Jul-1990    ml 4.00    Final for TT release. 
  90. ;            (Vectored-interrupts code not included)
  91. ;
  92. ; 31-Jul-1990    ml     Vectored-interrupt code included.
  93. ;
  94. ; 29-Oct-1990    ml 4.01    BUG!!!  Getcookie() module provided by AKP has a
  95. ;            variable declared in the bss.  This bss will be
  96. ;            clobbered when the driver adds GEMDOS buffers and
  97. ;            OS pool.  When getcookie() was called, and access 
  98. ;            the bss, it clobbered whatever was using its space
  99. ;            at the time.
  100. ;            Fixed in cookie.s by changing moving the variable
  101. ;            from the bss to the text segment.
  102. ;            (In cookie.s)
  103. ;
  104. ; 26-Nov-1990    ml 4.02    BUG!!  From 3.00 through 4.01, when Rwabs() is called
  105. ;            in raw mode, it ignored media change completely.
  106. ;            This created problems with cartridge swapping on the 
  107. ;            removable drives.  If Getbpb(), on a logical drive 
  108. ;            that has not been accessed on the previous cartridge,
  109. ;            is called right after a cartridge swap, Getbpb() will
  110. ;            call Rwabs() in raw mode to read the partition map of
  111. ;            the physical unit concerned.  This Rwabs() call will
  112. ;            get the media change error from the controller and 
  113. ;            ignores it without setting any mcflg of the physical
  114. ;            unit.  Now when Mediach(), on a logical drive that was
  115. ;            accessed on the previous cartridge, is called, the 
  116. ;            driver will return media not change!
  117. ;            In version 4.02, Rwabs() still does not return media
  118. ;            change error when called in raw mode, but will 
  119. ;            remember it  by setting the mcflgs of the physical 
  120. ;            unit concerned to maybe changed.
  121. ;-
  122.  
  123.  
  124. .include    "defs.h"
  125. .include    "error.h"
  126. .include    "sysvar.h"
  127. .include    "68030.s"
  128.  
  129.  
  130. .extern _untrdy
  131. .extern _rqsense
  132. .extern _hread
  133. .extern _hwrite
  134. .extern _xtdread
  135. .extern _xtdwrt
  136.  
  137. .extern    i_sasi1
  138. .extern    _getcookie
  139.  
  140. ;
  141. ;+
  142. ; Entry points:
  143. ;
  144. ;    +0   GEMDOS entry point (double-click, or \AUTO folder on floppy)
  145. ;    +4   Boot entry point (from driver file off of C:)
  146. ;    +8   Reserved for future use
  147. ;    +$C  $F0AD magic number
  148. ;    +$E  version number
  149. ;    +$12 # chunks of ospool to add
  150. ;    +$14 # of sqnpart entries that follows
  151. ;    +$16 first sqnpart entry
  152. ;
  153. ; if bootloaded, d0 = # bytes allocated by boot code.
  154. ;-
  155. i_sasi:    bra    gboot            ; GEMDOS entry-point
  156.     bra    iboot            ; Boot entry-point
  157.     bra    iboot            ; (unused, reserved)
  158.  
  159.  
  160. ;+
  161. ;  Patchable variables
  162. ;-
  163. magicnum:    dc.w    $f0ad        ; wasn't here in previous releases
  164. vernum:        dc.w    $0402        ; version number
  165. numchunks:    dc.w    128        ; # chunks of ospool to add
  166.         .globl    defbigsect
  167. defbigsect:    dc.w    512        ; default size of a big sector
  168. numsqnpart:    dc.w    MAXACSI        ; number of sqnpart entries to follow
  169.         .globl    defsqnpart
  170. defsqnpart:    dcb.b    MAXACSI,1    ; default # drives for rmvbl ACSI unit
  171.  
  172. ; They're NEW!! Introduced in this version:
  173. numsqcnpart:    dc.w    MAXSCSI        ; number of sqcnpart entries to follow
  174.         .globl    defsqcnpart
  175. defsqcnpart:    dcb.b    MAXSCSI,1    ; default # drives for rmvbl SCSI unit
  176.         .globl    scxltmout    
  177. scxltmout:    dc.l    12001        ; SCSI long-timeout (at least 1 min)
  178.         .globl    slwsclto    
  179. slwsclto:    dc.l    5000        ; SCSI stunit() long-timeout (25s)
  180.         .globl    slwscsto    
  181. slwscsto:    dc.l    42        ; SCSI stunit() short-timeout (205ms)
  182.         .globl    scltmout    
  183. scltmout:    dc.l    201        ; SCSI long-timeout (at least 1000 ms)
  184.         .globl    scstmout    
  185. scstmout:    dc.l    101        ; SCSI short-timeout (at least 500 ms)
  186. .even
  187.  
  188.  
  189. ;+
  190. ; GEMDOS entry;
  191. ;   find amount of memory availble and store in d0.l
  192. ;-
  193. gboot:    movea.l    4(sp),a2        ; a2 -> basepage
  194.     move.l    4(a2),d0        ; d0 = available memory
  195.     sub.l    (a2),d0            ;    = p_hitpa - p_lowtpa - basepage
  196.     sub.l    #$0100,d0
  197.     bra    i_sasi1            ; (continue with normal initialization)
  198.  
  199.  
  200. ;+
  201. ;  Boot entry;
  202. ;    set "bootloaded", record base address from boot loader, 
  203. ;    and continue with normal boot process.
  204. ;-
  205. iboot:    st    bootloaded        ; boot entry-point, set flag
  206.     sub.l    #$1c,d0            ; memory available -= file header
  207.     move.l    a2,baseaddr        ; install base address
  208.                     ; a2 = beginning addr of this block
  209.     bra    i_sasi1            ; (continue with normal initialization)
  210.  
  211.  
  212. ;
  213. ;+
  214. ; Driver State
  215. ;-
  216.         dc.b    13,'AHDI : Dec 06 1990 v4.02'
  217.         dc.b    13,10,$bd,'Atari Corp.'
  218.         dc.b    ' 1985, 1986, 1987, 1988, 1989, 1990'
  219.         dc.b    13,10,0,$1A
  220. .even
  221.  
  222. ;*****  Beginning Of Published Variables  *****
  223.  
  224.         .globl    puns
  225. puns:        dc.w    0        ; # of physical units on user's system
  226.  
  227. dummy1:        dcb.b    2,-1        ; dummy pun entries for A and B
  228.         .globl    pun
  229. pun:        dcb.b    MAXUNITS,0    ; physical unit table
  230. .even
  231.  
  232. dummy2:        dcb.l    2,0        ; dummy start entries for A and B
  233.         .globl    start
  234. start:        dcb.l    MAXUNITS,0    ; partition start table
  235.  
  236.         .globl    cookie        ; *** DON'T CHANGE ***
  237. cookie:        dc.l    $41484449    ; cookie = 'AHDI'
  238.  
  239.         .globl    cookptr
  240. cookptr:    dc.l    0        ; pointer to cookie
  241.  
  242. versn:        dc.w    $0402        ; version number: MMmm
  243.  
  244.         .globl    maxssz
  245. maxssz:        dc.w    512        ; maximum sector size allowed
  246.  
  247. spndown:    dc.l    0        ; time limit to spin down unit 0
  248.                     ; applicable to Stacy ONLY
  249.  
  250.         .globl    numacsi
  251. numacsi:    dc.w    0        ; number of ACSI drives
  252.  
  253.         dcb.w    29,0        ; reserved for future use
  254.  
  255. ;*****  End Of Published Variables  *****
  256.  
  257.     .globl    mcflgs
  258. mcflgs:    dcb.b    MAXUNITS,2        ; media change flag table
  259.     .globl    xst
  260. xst:    dcb.b    MAXUNITS,1        ; drive existence flag table
  261. bpbs:    dcb.b    BPBLEN,0        ; a bpb 
  262. serno:    dcb.b    MAXUNITS*SERLEN,0    ; serial number table
  263.     .globl    sratio
  264. sratio:    dcb.b    MAXUNITS,1        ; log sect size : phys sect size tbl
  265. fatsum:    dcb.b    MAXUNITS*FATLEN,0    ; FAT checksum table
  266. fatst:    dcb.w    MAXUNITS,0        ; starting sector # of last FAT
  267. fatend:    dcb.w    MAXUNITS,0        ; ending sector # of last FAT
  268.  
  269.         .globl    bootloaded
  270. bootloaded:    dc.w    0        ; nonzero if loaded from boot sector
  271.         .globl    memalloc
  272. memalloc:    dc.l    0        ; total memory available if bootloaded
  273. baseaddr:    dc.l    0        ; -> base addr of .PRG file
  274. tokeep:        dc.l    0        ; amount memory to keep
  275.  
  276.         .globl    cpun
  277. cpun:        dc.w    0        ; current physical unit
  278.         .globl    npart
  279. npart:        dc.w    0        ; number of partitions found
  280. bfat:        dc.w    0        ; 0: 12-bit FAT; 1: 16-bit FAT
  281.  
  282. strec:        dc.l    0        ; starting sector to read/write
  283. endrec:        dc.l    0        ; last sector to read/write
  284. stbuf:        dc.l    0        ; starting address of buffer
  285.         .globl    embscsi
  286. embscsi:    dc.b    0        ; 1: embedded SCSI drive
  287.  
  288. frbbuf:        dc.l    0        ; pointer to _FRB
  289.  
  290. _retries:    dc.w    NRETRIES    ; number of retries to do
  291. retrycnt:    dc.w    1        ; retry counter
  292.  
  293.         .globl    o_bpb
  294. o_bpb:        dc.l    1        ; old bpb vector
  295.         .globl    o_rw
  296. o_rw:        dc.l    1        ; old rwabs vector
  297.         .globl    o_mediach
  298. o_mediach:    dc.l    1        ; old media change vector
  299.  
  300.         .globl    sendata
  301. sendata:    dcb.b    32,0        ; buffer for sense data
  302.  
  303. lastmdctm:    dc.l    0        ; time media change was last called
  304.         .globl    pbuf
  305. pbuf:        dc.l    0        ; ptr to start of root sector image
  306. fsiz:        dc.w    0        ; FAT size in sectors
  307. fatrec:        dc.w    0        ; 2nd FAT starting sector
  308.         .globl    sizr
  309. sizr:        dc.w    1        ; ratio of log : phys sector size
  310. cstart:        dc.l    0        ; current dev's starting sector
  311. temp:        dc.l    0        ; temporary storage
  312.         .globl    savssp
  313. savssp:        dc.l    1        ; (saved SSP)
  314.         .globl    _cachexst
  315. _cachexst:    dc.b    0        ; 0: no cache    1: with cache
  316.         .globl    ext
  317. ext:        dc.b    0        ; if =0, not processing ext partition
  318.         .globl    extrt
  319. extrt:        dc.l    0        ; starting sector of ext DOS partition
  320.         .globl    extvol
  321. extvol:        dc.l    0        ; offset wrt ext DOS partition
  322. pbpb:        dc.w    0        ; partition # for dev
  323. .even
  324.  
  325.  
  326. ;
  327. ;+
  328. ; Front End
  329. ;-
  330.  
  331. ;+
  332. ;  Return pointer to BPB (or NULL)
  333. ;
  334. ;    Synopsis:    LONG hbpb(dev)
  335. ;        WORD dev;    4(sp).w
  336. ;-
  337.     .globl    hbpb
  338. hbpb:    move.w    4(sp),d0        ; d0 = devno
  339.     clr    d1            ; d1 = 0, physical op not possible
  340.     movea.l    o_bpb,a0        ; a0 -> pass-through vector
  341.     lea    _sasi_bpb(pc),a1    ; a1 -> our handler
  342.     bra.s    check_dev        ; do it
  343.  
  344.  
  345. ;+
  346. ;  Read or write logical sectors
  347. ;
  348. ;    Synopsis:    LONG hrw(rw, buf, count, recno, dev)
  349. ;        WORD rw;    $4(sp).w
  350. ;        char *buf;    $6(sp).l
  351. ;        WORD count;    $a(sp).w
  352. ;        WORD recno;    $c(sp).w
  353. ;        WORD dev;    $e(sp).w
  354. ;-
  355.     .globl    hrw
  356. hrw:    move.w    $e(sp),d0        ; d0 = devno
  357.     move.w    4(sp),d1        ; d1 includes physical device flag
  358.     movea.l    o_rw,a0            ; a0 -> pass-through vector
  359.     lea    _sasi_rw(pc),a1        ; a1 -> our handler
  360.     bra.s    check_dev        ; do it
  361.  
  362.  
  363. ;+
  364. ;  Check for media change
  365. ;
  366. ;    Synopsis:    LONG hmediach(dev)
  367. ;        WORD dev;    4(sp).w
  368. ;-
  369.     .globl    hmediach
  370. hmediach:
  371.     move.w    4(sp),d0        ; d0 = devno
  372.     clr    d1            ; physical operation not possible
  373.     movea.l    o_mediach,a0        ; a0 -> pass-through vector
  374.     lea    _sasi_mediach(pc),a1    ; a1 -> our handler
  375.  
  376.  
  377. ;+
  378. ;  check_dev - use handler, or pass vector through
  379. ;
  380. ;  Passed:    d0.w = device#
  381. ;        d1, bit 3  1=physical operation
  382. ;        a0 ->  old handler
  383. ;        a1 ->  new handler
  384. ;        a5 ->  $0000 (zero-page ptr)
  385. ;
  386. ;  Jumps-to:    (a1) if dev in range for this handler
  387. ;        (a0) otherwise
  388. ;-
  389. check_dev:
  390.     subq    #2,d0            ; lowest device is 2 (unit 0 or C:)
  391.     bmi.s    chkd_f            ; if lower, not one of ours
  392.  
  393.     btst    #3,d1            ; is this a physical unit operation?
  394.     beq.s    chkd_a            ; if not set, go to chkd_a
  395.  
  396.     cmp.w    numacsi,d0        ; a valid ACSI unit?
  397.     blt.s    chkd_s            ; if so, it's one of ours
  398.  
  399.     sub.w    #MAXACSI,d0        ; a SCSI unit number?
  400.     bmi.s    chkd_f            ; if lower, not one of ours
  401.  
  402.     move.w    puns,d1            ; d1.w = number of valid SCSI units
  403.     sub.w    numacsi,d1        ;      = total num - num ACSI
  404.     cmp.w    d1,d0            ; a valid SCSI unit?
  405.     bge.s    chkd_f            ; if higher, not one of ours
  406.     bra.s    chkd_s            ; else it IS one of of ours
  407.  
  408. chkd_a:    lea    pun,a2            ; pointer to pun map
  409.     tst.b    0(a2,d0.w)        ; must be positive for a real unit
  410.     bmi.s    chkd_f
  411. chkd_s:    movea.l    a1,a0            ; yes -- follow success vector
  412. chkd_f:    jmp    (a0)            ; do it
  413.  
  414.  
  415. ;
  416. ;+
  417. ; Medium-Level Driver
  418. ;-
  419.  
  420. ;+
  421. ; Return BPB for logical device
  422. ;
  423. ; Synopsis:    LONG _sasi_bpb(dev)
  424. ;        WORD dev;    $4(sp).w
  425. ;
  426. ; Returns:    NULL, or a pointer to the BPB buffer
  427. ;
  428. ; 10-21-88    ml.    I am not making a special case for non-removable
  429. ;            hard disk, because if a program uses Allan's
  430. ;            program to force a media change, the program 
  431. ;            should be getting the "Real" AND "New" BPB.
  432. ;            (The old (v1.7 and before) AHDI only index into
  433. ;            the bpbs table and return the pointer, without
  434. ;            actually go and read the boot sector of the dev.)
  435. ;-
  436. _sasi_bpb:
  437.     subq.w    #2,4(sp)        ; dev # excluding drv A and B
  438.     move.w    4(sp),d1        ; d1 = device number
  439.     lea    pun,a0            ; a0 -> pun table
  440.     adda.w    d1,a0            ; a0 -> pun @ dev's entry
  441.     moveq    #0,d2            ; coerce byte to word
  442.     move.b    (a0),d2            ; d2.w = pun that dev belongs to
  443.     move.w    d2,cpun            ; cpun = pun(dev)
  444.  
  445.     lea    xst,a1            ; a1 -> drive existence table
  446.     tst.b    (a1,d1.w)        ; does drive exist?
  447.     bne.s    bpbgo            ; if it does, go on normally
  448.                     ; else, see if it really doesn't exist
  449.     movem.l    d1/a0,-(sp)        ; save registers
  450.     move.w    d2,-(sp)        ; physical unit number
  451.     bsr    _untrdy            ; verify by doing test unit ready
  452.     addq.l    #2,sp            ; cleanup stack
  453.     movem.l    (sp)+,d1/a0        ; restore registers
  454.     tst.w    d0            ; return good status?
  455.     beq    badbpb            ; if yes, ie. medium has not changed
  456.                     ; therefore, dev still doesn't exist
  457.     moveq    #1,d0            ; else medium may have changed
  458.     bsr    s_mc_xst        ; set mcflgs and xst flags to 1's
  459.                     ; and go try to get BPB
  460. bpbgo:    move.l    _dskbufp,pbuf        ; pbuf -> 2nd half of 1K disk buf
  461.     add.l    #512,pbuf
  462.  
  463. bpb00:    move.l    a0,-(sp)        ; save ptr to pun(dev)
  464.     move.w    cpun,-(sp)        ; physical unit number
  465.     addq.w    #2,(sp)            ; unit # including A: and B:
  466.     clr.w    -(sp)            ; from sector 0
  467.     move.w    #1,-(sp)        ; read in 1 sector
  468.     move.l    pbuf,-(sp)        ; buffer to read into
  469.     move.w    #$a,-(sp)        ; in phys mode/ignore media change
  470.     bsr    _ahdi_rw        ; ahdi_rw($a, pbuf, 1, 0, cpun)
  471.     adda    #12,sp
  472.     movea.l    (sp)+,a0        ; restore ptr to pun(dev)
  473.     tst    d0            ; read successful?
  474.     beq.s    bpb0            ; if yes, go on normally
  475.                     ; else call up error handler
  476. bpberr:    move.l    a0,-(sp)        ; save ptr to pun(dev)
  477.     move.w    8(sp),d1        ; a0 = drive # excluding A: and B:
  478.     bsr    critic            ; call up critical error handler
  479.     move.l    (sp)+,a0        ; restore ptr to pun(dev)
  480.     cmpi.l    #CRITRETRY,d0        ; retry?
  481.     beq.s    bpb00            ; if so, go and try again
  482.     bra    badbpb            ; else return no BPB
  483.  
  484. bpb0:    move.w    cpun,d2            ; d2 = physical unit number of dev
  485.     move.w    #0,pbpb            ; pbpb = partition # dev corresponds
  486. bpb1:    cmp.b    -(a0),d2        ; pun that dev belongs to == (a0)?
  487.     bne.s    bpb2
  488.     addq.w    #1,pbpb
  489.     bra.s    bpb1
  490.  
  491. bpb2:    move.w    #MAXNPART,d1        ; do #MAXNPART times
  492.     movea.l    pbuf,a0            ; a0 -> beginning of root sector
  493.     cmpi.w    #SIG,DOSSIG(a0)        ; is root sector in DOS format?
  494.     bne.s    bpb3            ; if not, assume it's in GEMDOS format
  495.     bsr    dosbpb            ; else, handle it the DOS way
  496.     bra.s    bpb4            ; else, go get the bpb
  497. bpb3:    move.w    #1,bfat            ; 16 bit FAT always for GEMDOS
  498.     bsr    gembpb            ; handle it the GEMDOS way
  499. bpb4:    tst.w    d0            ; successful?
  500.     beq.s    bpbnf            ; if =0, no valid BPB found
  501.     bpl.s    bpb5            ; if +ive, valid BPB found
  502.     bra.s    badbpb            ; else no BPB found
  503.                     ; partition not found
  504. bpbnf:    lea    xst,a0            ; a0 -> drive existence table
  505.     move.w    4(sp),d0        ; d0 = dev number
  506.     clr.b    (a0,d0.w)        ; dev definitely does not exist
  507.     lea    mcflgs,a0        ; a0 -> mcflgs table
  508.     move.b    #2,(a0,d0.w)        ; set as medium has changed
  509.     bra.s    badbpb            ; can't find such a partition
  510.  
  511. bpb5:    move.l    d1,-(sp)        ; start_sector
  512.     move.w    8(sp),-(sp)        ; dev number
  513.     bsr    getbpb            ; getbpb(dev, start_sector)
  514.     addq.l    #6,sp            ; clean up stack
  515.     tst.l    d0            ; getbpb successful?
  516.     bpl.s    retbpb            ; if so, return ptr to bpb
  517. badbpb:    moveq    #0,d0            ; return no bpb found
  518. retbpb:    rts
  519.  
  520.  
  521. ;
  522. ;+
  523. ; dosbpb - find the DOS partition that corresponds to the requested
  524. ;       logical drive
  525. ; Passed:
  526. ;    a0 = buffer address for root sector
  527. ;    d1 = number of entries in partition map
  528. ;
  529. ; Assumed:
  530. ;    pbpbs = partition being looked for
  531. ;
  532. ; Returns:
  533. ;    d0.b = 0        if partition not found
  534. ;         = negative #    some kind of error
  535. ;         = positive #    system indicator of the partition
  536. ;    d1.l = starting sector of the partition (if it is found)
  537. ;-
  538. dosbpb:    adda.w    #DOSPM,a0        ; a0 -> partition map
  539. dbpb0:    movem.l    d1/a0,-(sp)        ; save count and offset
  540.     sf    ext            ; not dealing with ext partition
  541.     bsr    fdpart            ; find a partition
  542.     tst.b    d0            ; found any?
  543.     beq.s    dbpba            ; not a valid partition
  544.     cmpi.b    #5,d0            ; extended partition?
  545.     bne.s    dbpb1            ; if not, it's a regular partition
  546.     st    ext            ; else, it's an extended partition
  547.     move.l    #0,extvol        ; offset from start of partition = 0
  548.     move.l    d1,extrt        ; starting sector # of ext partition
  549. dbpbx:    bsr    fdnxt            ; find next logical drive
  550.     tst.b    d0            ; found any?
  551.     beq.s    dbpba            ; no logical drive found
  552.     bmi.s    dbpb2            ; error returned
  553.     cmpi.b    #5,d0            ; extended volume?
  554.     beq.s    dbpbx            ; if so, go find next logical drive
  555. dbpb1:    subq.w    #1,pbpb            ; partition that we want?
  556.     bpl.s    dbpb3            ; if not, continue the search
  557. dbpb2:    addq.l    #8,sp            ; else clean up stack
  558.     move.w    #0,bfat            ; assume partition has 12-bit fat
  559.     cmpi.b    #1,d0            ; 12-bit fat?
  560.     beq.s    dbpb22            ; if so, return
  561.     move.w    #1,bfat            ; else bflag = 1 for 16-bit fat
  562. dbpb22:    bra.s    dbpbr            ; and return
  563. dbpb3:    tst.b    ext            ; clun is in ext partition?
  564.     bne.s    dbpbx            ; if so, go find next ext vol
  565. dbpba:    movem.l    (sp)+,d1/a0        ; restore count and offset
  566.     adda    #16,a0            ; index to next entry in pmap
  567.     dbra    d1,dbpb0
  568.     moveq    #0,d0            ; partition not found!
  569. dbpbr:    rts
  570.  
  571.     
  572. ;+
  573. ; fdpart - find a DOS partition.
  574. ;
  575. ; Passed:
  576. ;    a0 = address to partition entry
  577. ;
  578. ; Returns:
  579. ;    d0.b = 0        partition is not valid
  580. ;         = positive    #    partition is a valid partition
  581. ;           (this is the system indicator of the partition)
  582. ;    d1.l = starting sector # of a valid partition (if d0.b = 1 or 4)
  583. ;         = starting sector # of extended partition (if d0.b = 5)
  584. ;-
  585.     .globl    fdpart
  586. fdpart:    tst.l    12(a0)            ; partition's size?
  587.     beq.s    fdp0            ; if =0, not valid
  588.  
  589.     move.b    4(a0),d0        ; d0 = system indicator
  590.     beq.s    fdpr            ; if =0, not valid
  591.  
  592.     cmpi.b    #4,d0            ; if =4, valid
  593.     beq.s    fdp1
  594.  
  595.     cmpi.b    #1,d0            ; if =1, valid
  596.     beq.s    fdp1
  597.  
  598.     cmpi.b    #5,d0            ; if =5, valid
  599.     beq.s    fdp1
  600.  
  601. fdp0:    moveq    #0,d0            ; else, not valid
  602.     bra.s    fdpr
  603.  
  604. fdp1:    move.l    8(a0),d1        ; d1.l = swapped starting sector #
  605.     ror.w    #8,d1            ; swap hi and lo byte of high word
  606.     swap    d1            ; swap hi and lo word
  607.     ror.w    #8,d1            ; swap hi and lo byte of low word
  608. fdpr:    rts
  609.  
  610.  
  611. ;+
  612. ; fdnxt - find a logical drive in the extended DOS partition
  613. ;
  614. ; Passed:
  615. ;    d0.b = (= 5 if a new extended volume was found)
  616. ;           (= 0 if nxtdrv was successful for last logical drive found)
  617. ;    d1.l = starting sector # of this extended volume
  618. ;    d2.b = count down for logical drive entries (if d0.b != 5)
  619. ;    a0.l = address of partition entry to be checked (if d0.b != 5)
  620. ;
  621. ; Assumes:
  622. ;    cpun = current physical unit #
  623. ;    extrt = starting sector # of extended DOS partition
  624. ;    extvol = offset from start of extended DOS partition (in sectors)
  625. ;
  626. ; Returns:
  627. ;    d0.b = 0        no logical drive found
  628. ;         = positive #    valid logical drive found
  629. ;           (this is the system indicator of the logical drive)
  630. ;         = negative #    error occured
  631. ;    d1.l = starting sector # of the logical drive (if d0.b = 1 or 4)
  632. ;         = starting sector # of next extended volume (if d0.b = 5)
  633. ;-
  634.     .globl    fdnxt
  635. fdnxt:    cmpi.b    #5,d0        ; new extended volume found?
  636.     bne.s    fdnxt0        ; if not, search for one
  637.     move.l    d1,-(sp)    ; from beginning of extended volume
  638.     move.w    cpun,-(sp)    ; physical unit number
  639.     addq.w    #2,(sp)        ; unit # including A: and B:
  640.     move.w    #-1,-(sp)    ; using a long sector number
  641.     move.w    #1,-(sp)    ; read in 1 sector
  642.     move.l    _dskbufp,-(sp)    ; buffer to read into
  643.     move.w    #$a,-(sp)    ; read in physical mode/ignore media change
  644.     bsr    _ahdi_rw    ; ahdi_rw($a, buf, 1, -1, cpun, lsectno)
  645.     adda    #16,sp        ; cleanup stack
  646.     tst.w    d0        ; read successful?
  647.     bne    fdnxtr        ; if not, return
  648.     
  649.     movea.l    _dskbufp,a0    ; else, 
  650.     cmpi.w    #SIG,DOSSIG(a0)    ; boot record valid?
  651.     bne.s    fdnxtr        ; if not, return no drive found
  652.                 ; (d0 already set by ahdi_rw)
  653.     adda.w    #DOSPM-16,a0    ; a0 -> 1st entry in log drive map
  654.     move.w    #MAXNPART+1,d2    ; d2 = count for # of log drive entries
  655.  
  656. fdnxt0:    subq.w    #1,d2        ; more entries to search?
  657.     bmi.s    fdnxt1        ; if not, return
  658.  
  659.     adda    #16,a0        ; a0 -> entry to be examined
  660.     tst.l    12(a0)        ; partition size's?
  661.     beq.s    fdnxt0        ; if =0, not valid
  662.  
  663.     move.b    4(a0),d0    ; d0 = system indicator
  664.     beq.s    fdnxt0        ; if =0, not valid
  665.  
  666.     move.l    8(a0),d1    ; d1.l = logical start sector of drv or vol
  667.     beq.s    fdnxt0        ; if =0, not valid
  668.     ror.w    #8,d1        ; swap hi and lo byte of high word
  669.     swap    d1        ; swap hi and lo word
  670.     ror.w    #8,d1        ; swap hi and lo byte of low word
  671.  
  672.     cmpi.b    #4,d0        ; if =4,
  673.     beq.s    fdnxt2        ; valid logical drive found
  674.  
  675.     cmpi.b    #1,d0        ; if =1,
  676.     beq.s    fdnxt2        ; valid logical drive found
  677.  
  678.     cmpi.b    #5,d0        ; if =5, valid ptr to next ext volume
  679.     bne.s    fdnxt0        ; else, not valid
  680.     move.l    d1, extvol    ; offset of ext vol from start of ext DOS
  681.     bra.s    fdnxt3
  682.  
  683. fdnxt1:    moveq    #0,d0        ; return no drive found
  684.     bra.s    fdnxtr
  685.  
  686. fdnxt2:    add.l    extvol,d1    ; d1 = start sector wrt beginning of ext DOS
  687. fdnxt3:    add.l    extrt,d1    ; d1 = start sector wrt beginning of disk
  688. fdnxtr:    rts
  689.  
  690.  
  691. ;
  692. ;+
  693. ; gembpb - find the GEMDOS partition that corresponds to the requested
  694. ;       logical drive.
  695. ; Passed:
  696. ;    a0 = buffer address for root sector
  697. ;    d1 = number of entries in partition map
  698. ;
  699. ; Assumed:
  700. ;    pbpbs = partition being looked for
  701. ;
  702. ; Returns:
  703. ;    d0.b = 0        if partition not found
  704. ;         = negative #    some kind of error
  705. ;         = positive #    system indicator of the partition
  706. ;    d1.l = starting sector of the partition (if it is found)
  707. ;-
  708. gembpb:    adda.w    #HDSIZ,a0        ; a0 -> hard disk size
  709.     tst.l    (a0)+            ; size? (a0 -> start of pmap)
  710.     beq.s    gbpb4            ; if =0, no drive will exist
  711. gbpb0:    movem.l    d1/a0,-(sp)        ; save count and offset
  712.     sf    ext            ; not dealing with ext partition
  713.     bsr    fgpart            ; find partitions
  714.     tst.b    d0            ; found any?
  715.     beq.s    gbpba            ; not a valid partition
  716.     cmpi.b    #'X',d0            ; extended partition?
  717.     bne.s    gbpb1            ; if not, it's a regular partition
  718.     st    ext            ; else, it's an extended partition
  719.     move.l    #0,extvol        ; offset from start of partition = 0
  720.     move.l    d1,extrt        ; starting sector # of ext partition
  721. gbpbx:    bsr    fgnxt            ; find next logical drive
  722.     tst.b    d0            ; found any?
  723.     beq.s    gbpba            ; no logical drive found
  724.     bmi.s    gbpb2            ; error returned
  725.     cmpi.b    #'X',d0            ; extended volume?
  726.     beq.s    gbpbx            ; if so, go find next logical drive
  727. gbpb1:    subq.w    #1,pbpb            ; partition that we want?
  728.     bpl.s    gbpb3            ; if not, continue the search
  729. gbpb2:    addq.l    #8,sp            ; else BINGO!  Clean up stack
  730.     bra.s    gbpbr            ; and return
  731. gbpb3:    tst.b    ext            ; clun is in ext partition?
  732.     bne.s    gbpbx            ; if so, go find next ext vol
  733. gbpba:    movem.l    (sp)+,d1/a0        ; restore count and offset
  734.     adda    #12,a0            ; index to next entry in pmap
  735.     dbra    d1,gbpb0
  736. gbpb4:    moveq    #0,d0            ; partition not found!
  737. gbpbr:    rts
  738.  
  739.  
  740. ;+
  741. ; fgpart - find a GEMDOS partition.
  742. ;
  743. ; Passed:
  744. ;    a0 = address to partition entry
  745. ;
  746. ; Returns:
  747. ;    d0.b = 0        partition is not valid
  748. ;         = positive    #    partition is a valid partition
  749. ;           (this is the first byte in p_id of the partition)
  750. ;    d1.l = starting sector # of a valid partition (if d0.b = 'G' or 'B')
  751. ;         = starting sector # of extended partition (if d0.b = 'X')
  752. ;-
  753.     .globl    fgpart
  754. fgpart:    tst.b    (a0)            ; check the valid partition flag
  755.     beq.s    fgp2            ; if =0, not valid
  756.  
  757.     tst.l    8(a0)            ; partition's size?
  758.     beq.s    fgp2            ; if =0, not valid
  759.  
  760.     cmpi.b    #'G',1(a0)        ; must find GEM as type
  761.     bne.s    fgp0            ; for REGULAR partition
  762.     cmpi.b    #'E',2(a0)        ; (ie., partition < 16Mb)
  763.     bne.s    fgp0
  764.     cmpi.b    #'M',3(a0)
  765.     beq.s    fgp3
  766.  
  767. fgp0:    cmpi.b    #'B',1(a0)        ; must find BGM as type
  768.     bne.s    fgp1            ; for BIG partition
  769.     cmpi.b    #'G',2(a0)        ; (ie., partition >= 16Mb)
  770.     bne.s    fgp1
  771.     cmpi.b    #'M',3(a0)
  772.     beq.s    fgp3
  773.  
  774. fgp1:    cmpi.b    #'X',1(a0)        ; or find XGM as type
  775.     bne.s    fgp2            ; for EXTENDED GEMDOS 
  776.     cmpi.b    #'G',2(a0)        ; partition
  777.     bne.s    fgp2            ; (ie., partition with
  778.     cmpi.b    #'M',3(a0)        ;  a linked list of
  779.     beq.s    fgp3            ;  logical drives)
  780.  
  781. fgp2:    moveq    #0,d0            ; else, not valid
  782.     bra.s    fgpr
  783.  
  784. fgp3:    move.l    4(a0),d1        ; d1.l = starting sector #
  785.     move.b    1(a0),d0        ; d0.b = first byte of p_id
  786. fgpr:    rts
  787.  
  788.  
  789. ;+
  790. ; fgnxt - find a logical drive in the extended GEMDOS partition
  791. ;
  792. ; Passed:
  793. ;    d0.b = (= 'X' if a new extended volume was found)
  794. ;           (= 0 if nxtdrv was successful for last logical drive found)
  795. ;    d1.l = starting sector # of this extended volume
  796. ;    d2.b = count down for logical drive entries (if d0.b != 'X')
  797. ;    a0.l = address of partition entry to be checked (if d0.b != 'X')
  798. ;
  799. ; Assumes:
  800. ;    cpun = current physical unit #
  801. ;    extrt = starting sector # of extended GEMDOS partition
  802. ;    extvol = offset from start of extended GEMDOS partition (in sectors)
  803. ;
  804. ; Returns:
  805. ;    d0.b = 0        no logical drive found
  806. ;         = positive #    valid logical drive found
  807. ;           (this is the first byte of p_id of the logical drive)
  808. ;         = negative #    error occured
  809. ;    d1.l = starting sector # of the logical drive (if d0.b = 'G' or 'B')
  810. ;         = starting sector # of next extended volume (if d0.b = 'X')
  811. ;-
  812.     .globl    fgnxt
  813. fgnxt:    cmpi.b    #'X',d0        ; new extended volume found?
  814.     bne.s    fgnxt0        ; if not, search for one
  815.     move.l    d1,-(sp)    ; from beginning of extended volume
  816.     move.w    cpun,-(sp)    ; physical unit number
  817.     addq.w    #2,(sp)        ; unit # including A: and B:
  818.     move.w    #-1,-(sp)    ; using a long sector number
  819.     move.w    #1,-(sp)    ; read in 1 sector
  820.     move.l    _dskbufp,-(sp)    ; buffer to read into
  821.     move.w    #$a,-(sp)    ; read in physical mode/ignore media change
  822.     bsr    _ahdi_rw    ; ahdi_rw($a, buf, 1, -1, cpun, lsectno)
  823.     adda    #16,sp        ; cleanup stack
  824.     tst.w    d0        ; read successful?
  825.     bne    fgnxtr        ; if not, return error
  826.  
  827.     movea.l    _dskbufp,a0    ; a0 -> partition map
  828.     adda.w    #HDSIZ+4-12,a0    ; a0 -> 1st entry in log drive map
  829.     move.w    #MAXNPART+1,d2    ; d2 = count for # of log drive entries
  830.  
  831. fgnxt0:    subq.w    #1,d2        ; more entries to search?
  832.     bmi.s    fgnxt3        ; if not, return
  833.  
  834.     adda    #12,a0        ; a0 -> entry to be examined
  835.     tst.l    8(a0)        ; partition size's?
  836.     beq.s    fgnxt0        ; if =0, not valid.  Try next entry
  837.  
  838.     tst.b    (a0)        ; check the valid partition flag
  839.     beq.s    fgnxt0        ; if =0, not valid.  Try next entry
  840.  
  841.     move.l    4(a0),d1    ; d1.l = logical start sector of drv or vol
  842.  
  843.     cmpi.b    #'G',1(a0)    ; must find GEM as type
  844.     bne.s    fgnxt1        ; for REGULAR partition
  845.     cmpi.b    #'E',2(a0)    ; (ie., partition < 16Mb)
  846.     bne.s    fgnxt1
  847.     cmpi.b    #'M',3(a0)
  848.     beq.s    fgnxt4
  849.  
  850. fgnxt1:    cmpi.b    #'B',1(a0)    ; must find BGM as type
  851.     bne.s    fgnxt2        ; for BIG partition
  852.     cmpi.b    #'G',2(a0)    ; (ie., partition >= 16Mb)
  853.     bne.s    fgnxt2
  854.     cmpi.b    #'M',3(a0)
  855.     beq.s    fgnxt4
  856.  
  857. fgnxt2:    cmpi.b    #'X',1(a0)    ; or find XGM as type
  858.     bne.s    fgnxt3        ; for EXTENDED GEMDOS 
  859.     cmpi.b    #'G',2(a0)    ; partition
  860.     bne.s    fgnxt3        ; (ie., partition with
  861.     cmpi.b    #'M',3(a0)    ;  a linked list of
  862.     bne.s    fgnxt0        ;  logical drives)
  863.  
  864.     move.l    d1, extvol    ; offset of ext vol from start of ext GEMDOS
  865.     bra.s    fgnxt5
  866.  
  867. fgnxt3:    moveq    #0,d0        ; return no drive found
  868.     bra.s    fgnxtr
  869.  
  870. fgnxt4:    add.l    extvol,d1    ; d1 = start sector wrt beginning of ext DOS
  871. fgnxt5:    add.l    extrt,d1    ; d1 = start sector wrt beginning of disk
  872.     move.b    1(a0),d0    ; d0.b = first byte of p_id
  873. fgnxtr:    rts
  874.  
  875.  
  876. ;
  877. ;+
  878. ; getbpb(dev, sectorno)
  879. ; WORD dev;        4(sp).w
  880. ; LONG sectorno;    6(sp).l
  881. ;
  882. ; Assume -
  883. ;    cpun contains physical unit number of dev
  884. ;-
  885. getbpb:    move.l    $6(sp),-(sp)    ; sector # of boot sector
  886.     move.w    cpun,-(sp)    ; physical unit
  887.     addq.w    #2,(sp)        ; unit # including A: and B:
  888.     move.w    #-1,-(sp)    ; using a long sector number
  889.     move.w    #1,-(sp)    ; 1 sector
  890.     move.l    _dskbufp,-(sp)    ; buffer
  891.     move.w    #$a,-(sp)    ; read in physical mode/ignore media change
  892.     bsr    _ahdi_rw    ; ahdi_rw(8, buf, 1, -1, cpun, lsectno)
  893.     adda    #16,sp        ; clean up stack
  894.     tst.w    d0        ; successful?
  895.     beq.s    getb0        ; if so, go on normally
  896.                 ; else let user retry
  897. getb9:    move.w    4(sp),d1    ; d1 = drive # excluding A: and B:
  898.     bsr    critic
  899.     cmpi.l    #CRITRETRY,d0    ; retry?
  900.     bne    getb7        ; if not, return
  901.     bra.s    getbpb        ; else read again
  902.  
  903. getb0:    movea.l    _dskbufp,a0    ; a0 -> boot sector image
  904.     movea.l    #bpbs,a2    ; a2 -> bpb
  905.  
  906.     move.w    #$0b,d0
  907.     bsr    getlhw
  908.     cmp.w    maxssz,d0    ; is sector size too big?
  909.     bhi    getb7        ; if it is, can't handle it
  910.     move.w    d0,(a2)+    ; =byt/sec
  911.     beq    getb7        ; if =0, bad data
  912.     move.w    d0,d1
  913.     divu    #512,d0        ; d0.b = ratio log : phys sector size
  914.     move.w    d0,sizr        ; save the ratio
  915.  
  916.     clr.w    d0
  917.     move.b    $d(a0),d0
  918.     move.w    d0,(a2)+    ; = #sectors/cluster
  919.     beq    getb7        ; if =0, bad data
  920.  
  921.     mulu    d1,d0
  922.     move    d0,(a2)+    ; = #bytes/cluster
  923.  
  924.     move    #$11,d0
  925.     bsr    getlhw        ; number of directory entries
  926.     tst    d0        ; num o' entries ?= 0
  927.     beq    getb7        ; if so, bad data
  928.      mulu    #32,d0        ; size of each entry
  929.     divu    d1,d0        ; number of sectors required
  930.     move.l    d0,d1
  931.     swap    d1
  932.     tst    d1
  933.     beq.s    getb1
  934.     addq    #1,d0        ; round up
  935. getb1:    move    d0,(a2)+    ; =rdlen
  936.     move    d0,d2
  937.  
  938.     move    #$16,d0
  939.     bsr    getlhw
  940.     move    d0,(a2)+    ; =FATsize
  941.     beq    getb7        ; if =0, bad data
  942.     move    d0,d1
  943.     move    d0,fsiz        ; save FAT size
  944.  
  945.     move    #$e,d0
  946.     bsr    getlhw        ; number of reserved sectors
  947.     add    d1,d0
  948.     move    d0,(a2)+    ; =2nd FAT start
  949.     move    d0,fatrec    ; save 2nd FAT start 
  950.  
  951.     add    d1,d0        ; plus size of second fat
  952.     add    d2,d0        ; plus rdlen
  953.     move    d0,(a2)+    ; = data start
  954.     move    d0,d2        ; save start of data
  955.  
  956.     move    #$13,d0
  957.     bsr    getlhw        ; number of sectors on media
  958.     sub    d2,d0        ; subtract # used by FATs,dir,boot
  959.     beq    getb7        ; if =0, bad data
  960.     clr.l    d1
  961.     move    d0,d1
  962.     clr    d0
  963.     move.b    $d(a0),d0    ; number of sectors/cluster
  964.     divu    d0,d1        ; rounding down
  965.     move    d1,(a2)+    ; =number of clusters
  966.     move    bfat,(a2)    ; =flags, 12 or 16 bit fats
  967.  
  968.     move.w    sizr,d2        ; d2 = current sector size ratio
  969.     lea    sratio,a1    ; a1 -> sector size ratio table
  970.     move.w    4(sp),d0    ; d0 = drive number
  971.     move.b    d2,(a1,d0.w)    ; update sector size ratio in table
  972.  
  973.     btst.b    #6,cpun+1    ; is unit removable?
  974.     beq    getb6        ; if not, can skip the fat checksum
  975.  
  976.     lea    serno,a1    ; a1 -> table of serial #s
  977.     mulu.w    #SERLEN,d0    ; dev# * SERLEN to index into table
  978.     adda.l    d0,a1        ; a1 -> serial # of dev
  979.     move.w    #SERLEN-1,d1    ; length of serial # - 1
  980. getb2:    move.b    $8(a0,d1.w),(a1,d1.w)    ; update serial # of dev
  981.     dbra    d1,getb2
  982.  
  983.     lea    fatsum,a2    ; a2 -> FAT check sum table
  984.     move.w    4(sp),d0    ; d0 = dev number
  985.     mulu    #FATLEN,d0    ; d0*FATLEN = to index into table
  986.     adda.l    d0,a2        ; a2 -> FAT check sum tbl of dev
  987.  
  988.     move.w    fatrec,d0    ; d0 = log starting sector of 2nd FAT
  989.     mulu    d2,d0        ; (in 512-byte sectors)
  990.     movea.l    $6(sp),a1    ; a1 = starting sector of drive
  991.     adda.l    d0,a1        ; a1 = phys starting sector of 2nd FAT
  992.  
  993.     move.w    fsiz,d1        ; d1 = # FAT sectors to read
  994.     subq.l    #1,d1        ;    = FAT size - 1
  995.  
  996. getb3:    move.w    sizr,d2        ; d2 = count per FAT sector
  997.     subq.w    #1,d2
  998.      clr.l    temp        ; initialize the sum
  999. getb4:    movem.l    d1-d2/a0-a2,-(sp)    ; save registers
  1000.     move.l    a1,-(sp)    ; from sector a1
  1001.     move.w    cpun,-(sp)    ; physical unit
  1002.     addq.w    #2,(sp)        ; unit # including A: and B:
  1003.     move.w    #-1,-(sp)    ; using a long sector number
  1004.     move.w    #1,-(sp)    ; read 1 phys sector
  1005.     move.l    a0,-(sp)    ; buffer (in _dskbufp)
  1006.     move.w    #$a,-(sp)    ; read in physical mode/ignore media change
  1007.     bsr    _ahdi_rw    ; ahdi_rw($a, buf, 1, -1, cpun, lsecno)
  1008.     adda    #16,sp        ; clean up stack
  1009.     movem.l    (sp)+,d1-d2/a0-a2    ; restore registers
  1010.     tst.w    d0        ; read successful?
  1011.     beq    getb5        ; if so, go on normally
  1012.                 ; else let user retry
  1013. getba:    movem.l    d1-d2/a0-a2,-(sp)    ; save registers
  1014.     move.w    24(sp),d1    ; d1 = drive # excluding A: and B:
  1015.     bsr    critic        ; critical error handler
  1016.     movem.l    (sp)+,d1-d2/a0-a2    ; restore registers
  1017.     cmpi.l    #CRITRETRY,d0    ; retry?
  1018.     beq.s    getb4        ; if so, try again
  1019.     bra    getb7        ; else return
  1020.  
  1021. getb5:    bsr    bsum        ; add up values in the sector
  1022.     addq    #1,a1        ; get ready for next sector
  1023.     dbra    d2,getb4    ; until one logical FAT sector is done
  1024.  
  1025.     bsr    csum        ; find the checksum
  1026.     move.b    d0,(a2)+    ; update checksum for this FAT sector
  1027.     dbra    d1,getb3    ; until all sectors are checked
  1028.  
  1029. getb6:    move.w    $4(sp),d0    ; d0 = dev number
  1030.     lea    mcflgs,a0    ; load address of mcflgs table
  1031.     clr.b    (a0,d0.w)    ; clear mcflg for dev
  1032.  
  1033.     lea    xst,a0        ; a0 -> drive existence table
  1034.     move.b    #2,(a0,d0.w)    ; dev definitely exists
  1035.  
  1036.     lea    fatst,a0    ; a0 -> FAT start sector table
  1037.     asl.w    #1,d0        ; offset = dev# * 2 (tbl of words)
  1038.     move    fatrec,(a0,d0.w); update FAT starting sect#
  1039.  
  1040.     lea    fatend,a0    ; a0 -> FAT end sector table
  1041.     move.w    fatrec,d1    ; d1 = fatend(dev)
  1042.     add.w    fsiz,d1        ;    = fatrec + fsiz - 1
  1043.     subq.w    #1,d1    
  1044.     move.w    d1,(a0,d0.w)    ; fatend(dev) = fatrec + fsiz - 1
  1045.  
  1046.     lea    start,a0    ; a0 -> beginning of start table
  1047.     asl.w    #1,d0        ; offset = dev# * 2 * 2 (tbl of longs)
  1048.     move.l    $6(sp),(a0,d0.w); update starting sect# of dev
  1049.  
  1050.     move.l    #bpbs,d0    ; no errors, return ptr to BPB
  1051.     bra.s    getb8        ; return
  1052.  
  1053. getb7:    moveq    #-1,d0        ; error
  1054. getb8:    rts
  1055.  
  1056.  
  1057. ;+
  1058. ; WORD getlhw(d0=offset)
  1059. ; returns word (low,high) from 0(D0,A0)
  1060. ;-
  1061.     .globl    getlhw
  1062. getlhw:    move    d1,-(sp)    ; preserve d1
  1063.     move.b    1(a0,d0.w),d1
  1064.     lsl.w    #8,d1
  1065.     move.b    0(a0,d0.w),d1
  1066.     move    d1,d0
  1067.     move    (sp)+,d1
  1068.     rts
  1069.  
  1070.  
  1071. ;+
  1072. ; bsum
  1073. ;
  1074. ; Passed:
  1075. ;    a0 = starting address of buffer to be summed
  1076. ;    temp.l = current sum
  1077. ;
  1078. ; Function:
  1079. ;      - sum up 512 bytes of a buffer 4 bytes at a time
  1080. ;    - save the sum in temp.l
  1081. ;
  1082. ; Algorithm for check summing the FAT:
  1083. ;    - add up bytes in the buffer 4 bytes at a time    (in bsum)
  1084. ;    - if the sum is non-zero, XOR the high word     (in csum)
  1085. ;      with the low word of the 4-byte result
  1086. ;    - now take this 2-byte result, and XOR its high    (in csum)
  1087. ;      byte with its low byte to get the final 1-byte
  1088. ;      result
  1089. ;-
  1090. bsum:    movem.l    d1/a0,-(sp)        ; save d1, a0
  1091.     move.l    temp,d0            ; d0 = current sum
  1092.     move    #127,d1            ; count
  1093. bsum0:    add.l    (a0)+,d0        ; add 4 bytes to sum
  1094.     dbra    d1,bsum0        ; until all bytes are added
  1095.     move.l    d0,temp            ; temp.l = new sum
  1096.     movem.l    (sp)+,d1/a0        ; restore d1, a0
  1097.     rts
  1098.  
  1099.  
  1100. ;+
  1101. ; csum
  1102. ; (a) XOR the high word with the low word of temp.l
  1103. ; (b) then XOR the high byte with the low byte of result of (a)
  1104. ;
  1105. ; Returns:
  1106. ;    d0.b = checksum
  1107. ;-
  1108. csum:    move.w    temp+2,d0        ; d0.w = low word of result
  1109.     eor.w    d0,temp            ; exclusive-or low and high word
  1110.     move.b    temp+1,d0        ; d0.b = low byte of xor-ed result
  1111.     eor.b    d0,temp            ; exclusive-or low and high byte
  1112.     move.b    temp,d0
  1113.     rts                ; d0.b = checksum
  1114.  
  1115.  
  1116. ;
  1117. ;+
  1118. ;  Read/Write sectors
  1119. ;
  1120. ;    Synopsis:    _ahdi_rw(rw, buf, count, recno, dev, lrecno)
  1121. ;        WORD rw        4(sp).w        ; non-zero -> write
  1122. ;        char *buf    6(sp).l
  1123. ;        WORD count    $a(sp).w
  1124. ;        WORD recno    $c(sp).w
  1125. ;        WORD dev    $e(sp).w
  1126. ;        LONG lrecno    $10(sp).l    ; optional
  1127. ;-
  1128.  
  1129. ; stack frame offsets
  1130. xrw    equ    8
  1131. xbuf    equ    10
  1132. xcount    equ    14
  1133. xrecno    equ    16
  1134. xdev    equ    18
  1135. xlrecno    equ    20
  1136.  
  1137.     .globl    _sasi_rw
  1138.     .globl    _ahdi_rw
  1139. _sasi_rw:
  1140. _ahdi_rw:
  1141.     link    a6,#0            ; create a frame pointer
  1142.     subq.w    #2,xdev(a6)        ; drive # excluding A: and B:
  1143.  
  1144.     move.w    xdev(a6),d0        ; d0 = device number
  1145.     btst.b    #3,xrw+1(a6)        ; is this a physical operation?
  1146.     beq.s    getcpun            ; if not, find physical unit number
  1147.     move.w    d0,cpun            ; else, dev# passed is phys unit #
  1148.     move.w    #1,sizr            ; sector size ratio = 1
  1149.     bra    ahrw1            ; go start the r/w
  1150. getcpun:                ; map log -> phys unit number
  1151.     lea    pun,a0            ; a0 -> pun table
  1152.     move.b    (a0,d0.w),cpun+1    ; cpun = pun of dev
  1153.     
  1154.     lea    sratio,a0        ; a0 -> sector size ratio table
  1155.     move.b    (a0,d0.w),sizr+1    ; sizr = current sector size ratio
  1156.                     ;     (coerced to word)
  1157.     lea    start,a0        ; a0 -> start table
  1158.     move.w    d0,d1            ; d1 = drive #
  1159.     add.w    d1,d1            ; d1*2*2 (index into tbl of longs)
  1160.     add.w    d1,d1
  1161.     move.l    (a0,d1.w),cstart    ; cstart = dev starting sector
  1162.  
  1163.     btst.b    #1,xrw+1(a6)        ; ignore media change?
  1164.     bne    ahrw1            ; if yes, go ahead and do r/w
  1165.                     ; else check for media change
  1166.     lea    mcflgs,a0        ; a0 -> mcflgs of drive
  1167.     move.b    (a0,d0.w),d0        ; d0 = mcflg of dev
  1168.     beq    ahrw1            ; if media not changed, go do r/w
  1169.  
  1170.     cmpi.b    #2,d0            ; is media definitely changed?
  1171.     beq    retmc            ; if yes, return media has changed
  1172.                     ; else, check if media has changed
  1173.                     ; try to read dev's boot sector
  1174. chkmc:    move.l    cstart,-(sp)        ; dev starting sector
  1175.     move.w    cpun,-(sp)        ; physical unit number
  1176.     addq.w    #2,(sp)            ; unit # including A: and B:
  1177.     move.w    #-1,-(sp)        ; using a long sector number
  1178.     move.w    #1,-(sp)        ; 1 sector
  1179.     move.l    _dskbufp,-(sp)        ; buffer
  1180.     move.w    #$a,-(sp)        ; phys mode and no media change error
  1181.     bsr    _ahdi_rw        ; ahdi_rw($a, buf, 1, -1, cpun, sectno)
  1182.     adda    #16,sp            ; clean up stack
  1183.     tst.w    d0            ; read successful?
  1184.     beq.s    chkser            ; yes, go check serial number
  1185.  
  1186.     move.w    xdev(a6),d1        ; device number
  1187.     bsr    critic            ; call critical error handler
  1188.     cmpi.l    #CRITRETRY,d0        ; is it the magic RETRY code?
  1189.     beq.s    chkmc            ; if yes, go back and try it
  1190.     bra    ahrw7            ; else return
  1191.  
  1192. chkser:    lea    serno,a1        ; a1 -> serial #s table
  1193.     move.w    xdev(a6),d0        ; d0 = dev number
  1194.     mulu.w    #SERLEN,d0        ; *SERLEN for index into table
  1195.     adda.l    d0,a1            ; a1 -> serial # of dev
  1196.  
  1197.     move.l    _dskbufp,a2        ; a2 -> boot sector
  1198.     addq.w    #8,a2            ; a2 -> serial # in boot sector
  1199.      move.w    #SERLEN-1,d0        ; d0 = count for comparison
  1200. cmpser:    cmpm.b    (a2)+,(a1)+        ; serial # read ?= serial # recorded
  1201.     bne    ismc            ; if not, media has changed
  1202.     dbra    d0,cmpser        ; compare next byte of serial #
  1203.                     ; serial # hasn't changed, try FAT
  1204.     move.w    xdev(a6),d0        ; d0 = dev number
  1205.     lea    fatsum,a1        ; a1 -> fat checksum table
  1206.     move.w    #FATLEN,d1        ; d1.w = index into table
  1207.     mulu    d0,d1
  1208.     adda.l    d1,a1            ; a1 -> fat checksum of dev
  1209.  
  1210.     add.w    d0,d0            ; d0*2 = index into table of words
  1211.     lea    fatst,a2        ; a2 -> FAT start table
  1212.     move.w    (a2,d0.w),fatrec    ; fatrec = fatst(dev)
  1213.  
  1214.     lea    fatend,a2        ; a2 -> FAT end table
  1215.     move.w    (a2,d0.w),d1        ; d1 = counter to scan FAT table
  1216.     sub.w    fatrec,d1        ;    = fatend(dev) - fatst(dev)
  1217.  
  1218.     movea.l    cstart,a2        ; a2 = start sector of dev
  1219.     move.w    fatrec,d2        ; d2 = fatst(dev)
  1220.     mulu    sizr,d2            ; d2 = fatst(dev) in 512-byte sector
  1221.     adda.l    d2,a2            ; a2 = phys start sector of 2nd FAT
  1222.  
  1223.     movea.l    _dskbufp,a0        ; a0 -> dskbuf
  1224. cmpfat:    move.w    sizr,d2            ; d2 = # reads per FAT sector
  1225.     subq.w    #1,d2            ; d2 - 1 = counter
  1226.     clr.l    temp            ; initialize sum
  1227. cfat0:    movem.l    d1-d2/a0-a2,-(sp)    ; save d1, d2, a0, a1, a2
  1228.                     ; try to read this FAT sector
  1229.     move.l    a2,-(sp)        ; at sector a2
  1230.     move.w    cpun,-(sp)        ; physical unit number
  1231.     addq.w    #2,(sp)            ; unit # including A: and B:
  1232.     move.w    #-1,-(sp)        ; using a long sector number
  1233.     move.w    #1,-(sp)        ; 1 sector
  1234.     move.l    a0,-(sp)        ; buffer
  1235.     move.w    #$a,-(sp)        ; phys mode and no media change error
  1236.     bsr    _ahdi_rw        ; ahdi_rw($a, buf, 1, -1, cpun, sectno)
  1237.     adda    #16,sp            ; clean up stack
  1238.     movem.l    (sp)+,d1-d2/a0-a2    ; restore d1, d2, a0, a1, a2
  1239.     tst.w    d0            ; read successful?
  1240.     beq.s    chkfat            ; if yes, go check sum FAT sectors
  1241.                     ; else assume it's read error
  1242.     movem.l    d1-d2/a0-a2,-(sp)    ; save registers d1, d2, a0, a2
  1243.     move.w    xdev(a6),d1        ; drive number
  1244.     bsr    critic
  1245.     movem.l    (sp)+,d1-d2/a0-a2    ; restore registers d1, d2, a0, a2
  1246.     cmpi.l    #CRITRETRY,d0        ; is it the magic RETRY code?
  1247.     beq.s    cfat0            ; if yes, go back and try it
  1248.     bra    ahrw7            ; else return
  1249.  
  1250. chkfat:    bsr    bsum            ; if ok, sum the sector
  1251.     addq    #1,a2            ; ready for try next sector
  1252.     dbra    d2,cfat0        ; until one FAT sector is summed
  1253.  
  1254.     bsr    csum            ; find the checksum
  1255.     cmp.b    (a1)+,d0        ; checksum recorded ?= checksum found
  1256.     bne    ismc            ; if not, media has changed
  1257.     dbra    d1,cmpfat        ; until all sectors are checked
  1258.  
  1259.     lea    mcflgs,a0        ; a0 -> mcflgs table
  1260.     adda.w    xdev(a6),a0        ; a0 -> mcflg of drive
  1261.     clr.b    (a0)            ; clear mcflg for dev
  1262.  
  1263. ahrw1:    tst.w    xcount(a6)        ; any sector to r/w?
  1264.     beq    ahrw6            ; if =0, done
  1265.  
  1266.     cmpi.w    #-1,xrecno(a6)        ; does recno = -1?
  1267.     bne.s    ahrw2            ; if not, we have a word record #
  1268.     movea.l    xlrecno(a6),a1        ; a1.l = start record #
  1269.     bra.s    ahrw3
  1270. ahrw2:    moveq    #0,d0            ; coerce to long
  1271.     move.w    xrecno(a6),d0        ; d0.l = recno
  1272.     movea.l    d0,a1            ; a1.l = start record #
  1273.  
  1274. ahrw3:    move.l    a1,strec        ; save first sector to r/w
  1275.     move.l    a1,d1            ; d1.l = starting sector to r/w
  1276.     moveq    #0,d2            ; coerce to long
  1277.     move.w    xcount(a6),d2        ; d2.l = #sectors to r/w
  1278.     adda.l    d2,a1            ; a1.l = last sector to r/w
  1279.     subq.l    #1,a1            ;      = first sector + count - 1
  1280.     move.l    a1,endrec        ; save last sector to r/w
  1281.     move.l    xbuf(a6),stbuf        ; save starting buffer address
  1282.  
  1283.     btst.b    #3,xrw+1(a6)        ; physical operation?
  1284.     bne.s    ahrw4            ; if so, ready to r/w
  1285.                     ; else log -> phys sector mapping
  1286.     mulu    sizr,d1            ; d1.l    = phys start sector to r/w
  1287.     add.l    cstart,d1        ;    = dev start sect + sect #
  1288.     mulu    sizr,d2            ; d2.l = # phys 512-byte sects to r/w
  1289.  
  1290. ahrw4:    move.w    xdev(a6),-(sp)        ; device # (excluding A: and B:)
  1291.     move.l    d1,-(sp)        ; starting sector
  1292.     move.l    d2,-(sp)        ; count (in sectors)
  1293.     move.l    xbuf(a6),-(sp)        ; buffer
  1294.     move.w    xrw(a6),-(sp)        ; read write flag
  1295.     bsr    _do_rw            ; do the read or write
  1296.     adda    #16,sp            ; clean up stack
  1297.     tst.l    d0            ; successful?
  1298.     beq.s    chkwr            ; if so, go on to wrap up
  1299.  
  1300.     cmpi.l    #E_CHNG,d0        ; media change detected?
  1301.     bne    ahrw7            ; if not, give up
  1302.     btst.b    #3,xrw+1(a6)        ; is this a physical operation?
  1303.     bne    ahrw7            ; if so, return media change error
  1304.     bra    chkmc            ; and go check if media has changed 
  1305.                     ; check if wrote to boot sector
  1306. chkwr:    move.w    xrw(a6),d0        ; d0 = r/w and flags word
  1307.     btst    #0,d0            ; read or write?
  1308.     beq    ahrw6            ; if read, done
  1309.     btst.b    #6,cpun+1        ; is drive removable?
  1310.     beq    ahrw6            ; if not, done
  1311.     btst    #3,d0            ; was it a physical operation?
  1312.     bne    ahrw6            ; if it was, done
  1313.     tst.l    strec            ; wrote to boot sector?
  1314.     bne.s    wrfat            ; if not, check if wrote to FATs
  1315.     lea    mcflgs,a0        ; else, a0 -> mcflgs table
  1316.     adda.w    xdev(a6),a0        ; a0 -> dev's mcflg
  1317.     move.b    #2,(a0)            ; assume medium has changed
  1318.                     ; check if wrote to FATs
  1319. wrfat:    lea    fatend,a0        ; a0 -> fatend table
  1320.     move.w    xdev(a6),d0        ; d0 = device number
  1321.     add.w    d0,d0            ; d0*2 = index into table of words
  1322.     moveq    #0,d1            ; coerce to long
  1323.     move.w    (a0,d0.w),d1        ; d1 = last sector of last FAT
  1324.     cmp.l    strec,d1        ; wrote beyond the last FAT?
  1325.     blt    ahrw6            ; if so, done
  1326.  
  1327.     lea    fatst,a0        ; a0 -> fatst table
  1328.     moveq    #0,d2            ; coerce to long
  1329.     move.w    (a0,d0.w),d2        ; d2 = first sector of last FAT
  1330.     cmp.l    endrec,d2        ; wrote before the last FAT?
  1331.     bgt    ahrw6            ; if so, done
  1332.                     ; else update FAT sector checksums
  1333.     move.l    stbuf,a0        ; a0 -> buffer w/ written data
  1334.     lea    fatsum,a1        ; a1 -> start of fatsum table
  1335.     move.w    xdev(a6),d0        ; d0 = dev number
  1336.     mulu.w    #FATLEN,d0        ; d0 = offset to dev's FAT chksum
  1337.     adda.l    d0,a1            ; a1 -> dev's first FAT chksum
  1338.     move.l    strec,d0        ; d0 = first sector wrote to
  1339.     sub.l    d2,d0            ; d0 = strec - start(last FAT)
  1340.     beq.s    wrfat2            ; if strec = start(last FAT), 
  1341.                     ;     no adjustments needed
  1342.      blt.s    wrfat1            ; if strec < start(last FAT)
  1343.                     ;     begin from start(last FAT)
  1344.     move.l    strec,d2        ; else begin from strec
  1345.     adda.l    d0,a1            ; a1 -> fatsum to be updated
  1346.     bra.s    wrfat2
  1347.  
  1348. wrfat1:    neg.l    d0            ; d0 = index into stbuf
  1349.     asl.l    #8,d0            ;    = (start(last FAT) - strec)*512
  1350.     add.l    d0,d0
  1351.     adda.l    d0,a0            ; a0 -> addr of buf for update
  1352.  
  1353. wrfat2:    cmp.l    endrec,d1        ; if end(last FAT) <= endrec
  1354.     ble.s    wrfat3            ;     stop at end(last FAT)
  1355.     move.l    endrec,d1        ; else stop at endrec
  1356.  
  1357. wrfat3:    sub    d2,d1            ; d1 = # sectors to be processed
  1358. wrfat4:    move.w    sizr,d2            ; d2 = # phys sect per log sect
  1359.     subq.w    #1,d2            ; dbra likes one less
  1360.     clr.l    temp            ; initialize sum
  1361. wrfat5:    bsr    bsum            ; sum up one 512-byte sector
  1362.     adda.l    #512,a0            ; point to next 512 bytes
  1363.     dbra    d2,wrfat5        ; until one logical sector is done
  1364.     bsr    csum            ; obtain checksum
  1365.     move.b    d0,(a1)+        ; record new fat checksum
  1366.     dbra    d1,wrfat4        ; do until all are updated
  1367.  
  1368. ahrw6:    clr.l    d0            ; got here with no errors!
  1369.     bra.s    ahrw7
  1370.  
  1371. ismc:    lea    mcflgs,a0        ; a0 -> mcflgs table
  1372.     adda.w    xdev(a6),a0        ; a0 -> dev's mcflg
  1373.     move.b    #2,(a0)            ; set mcflg for dev to has changed
  1374.     lea    xst,a0            ; a0 -> drive existence table
  1375.     adda.w    xdev(a6),a0        ; a0 -> xst flag of dev
  1376.     move.b    #2,(a0)            ; assume dev exists
  1377. retmc:    move.l    #E_CHNG,d0        ; yes, return media change error
  1378.  
  1379. ahrw7:    btst.b    #0,xrw+1(a6)        ; read or write?
  1380.     bne.s    ahrwd            ; if write, done
  1381.     tst.b    _cachexst        ; does a cache exist?
  1382.     beq.s    ahrwd            ; if not, done
  1383.                     ; else dump the cache
  1384.     move.l    d0,-(sp)        ; save the status
  1385.     move    sr,-(sp)        ; go to IPL 7
  1386.     ori    #$700,sr        ; no interrupts right now kudasai
  1387.     movecacrd0            ; d0 = (cache control register)
  1388.     ori.w    #$808,d0        ; dump both the D and I cache
  1389.     moved0cacr            ; update cache control register
  1390.     move    (sp)+,sr        ; restore interrupt state
  1391.     move.l    (sp)+,d0        ; restore the return value
  1392.  
  1393. ahrwd:    unlk    a6
  1394.     rts
  1395.  
  1396.  
  1397. ;+
  1398. ; smove() - Copy unaligned sectors (this is *supposed* to be slow!)
  1399. ;
  1400. ; Passed:
  1401. ;    d0 = # of sectors to be moved
  1402. ;    d1 = size of operation    (0 - byte; 2 - long;)
  1403. ;    a2 -> source buffer
  1404. ;    a1 -> dest buffer
  1405. ;
  1406. ; Trashes: d0, a1, a2
  1407. ;-
  1408. smove:    move.w    d1,-(sp)        ; save size of operation
  1409.     neg.w    d1            ; d0 = count
  1410.     addi.w    #9,d1            ;    = (# sectors * 512) >> op size
  1411.     asl.w    d1,d0            ;
  1412.     subq.w    #1,d0            ; dbra likes one less
  1413.     move.w    (sp)+,d1        ; restore operation size
  1414.     bne.s    smove2            ; if non-zero, use move longs
  1415.  
  1416. smove1:    move.b    (a2)+,(a1)+
  1417.     dbra    d0,smove1
  1418.     rts
  1419.  
  1420. smove2:    move.l    (a2)+,(a1)+
  1421.     dbra    d0,smove2
  1422.     rts
  1423.  
  1424.  
  1425. ;
  1426. ;+
  1427. ; _do_rw - called to read/write no more than 128K to an even boundary
  1428. ;
  1429. ; Passed:
  1430. ;    rw    4(sp).w        ; non-zero -> write
  1431. ;    buf    6(sp).l
  1432. ;    count    $a(sp).l    ; in # phys (512-byte) sectors
  1433. ;    recno    $e(sp).l    ; physical starting sector for r/w
  1434. ;    dev    $12(sp).w    ; log dev # exluding A: and B:
  1435. ;
  1436. ; Assumes:
  1437. ;    cpun = current physical unit to r/w
  1438. ;    if in logical mode, cstart = physical starting sector # of curr dev
  1439. ;
  1440. ; Mar-05-1990 ml.
  1441. ;    All I/O to ACSI and SCSI non-accessible memory will be done by
  1442. ; using the fast ram buffer (if there is one) or the diskbuf as an inter-
  1443. ; mediate stop for the transfer.
  1444. ;
  1445. ; ACSI accessible memory:    $00000000 -> $003fffff
  1446. ;                $ff000000 -> $ff3fffff
  1447. ; SCSI non-accessible 
  1448. ; memory on the TT:        $c0000000 -> $fcffffff
  1449. ;                $fe000000 -> $feffffff
  1450. ;
  1451. ; Mar-07-1990 ml.
  1452. ;    Do not have to take care of cases when Rwabs() is supplied with
  1453. ; a buffer that would cross different kinds of memory.
  1454. ; ("It's deadly!" said AKP. :) )
  1455. ;-
  1456. yrw    equ    $8
  1457. ybuf    equ    $a
  1458. ycount    equ    $e
  1459. yrecno    equ    $12
  1460. ydev    equ    $16
  1461.  
  1462. ; Memory that ACSI _can_ DMA to
  1463. STDUAL    equ    $003fffff    ; upper limit of ST dual-purpose RAM
  1464. STCMPIL    equ    $ff000000    ; lower limit of ST compatible image
  1465. STCMPIH    equ    $ff3fffff    ; upper limit of ST compatible image
  1466.  
  1467. ; Memory that SCSI _cannot_ DMA to (non-DW)
  1468. A32D16L    equ    $c0000000    ; lower limit of A32:D16 Memory/Peripherals
  1469. A32D16H    equ    $fcffffff    ; upper limit of A32:D16 Memory/Peripherals 
  1470. VA24D16    equ    $fe000000    ; lower limit of VMEbus A24:D16
  1471. VA16D16    equ    $feffffff    ; upper limit of VMEbus    A16:D16
  1472.  
  1473. ; Cookies
  1474. _FRB    equ    $5f465242        ; _FRB
  1475.  
  1476. _do_rw:    link    a6,#0            ; create a frame pointer
  1477.     move.l    ycount(a6),d2        ; d2.l = # sectors requested to r/w
  1478.      movea.l    ybuf(a6),a1        ; a1.l = buffer addr to r/w
  1479.     btst.b    #3,cpun+1        ; talking SCSI?
  1480.     bne    scrw0            ; if yes, go for it
  1481.                     ; else talk ACSI
  1482.     cmp.l    #MAXACSECTS,d2        ; more than one ACSI DMAful?
  1483.     bls.s    acrw1            ; if not, ready to r/w
  1484.     move.l    #MAXACSECTS,d2        ; else r/w only one ACSI DMAful
  1485.  
  1486. acrw1:    btst.b    #0,ybuf+3(a6)        ; buffer on odd boundary?
  1487.     bne.s    itrw0            ; if so, do intermediate transfer
  1488.  
  1489.     cmpa.l    #STDUAL,a1        ; buf within ACSI accessible memory?
  1490.     bls    rw1            ; if so, go ahead with the I/O
  1491.     cmpa.l    #STCMPIL,a1        ; else, do intermediate transfer
  1492.     bcs.s    itrw0
  1493.     cmpa.l    #STCMPIH,a1
  1494.     bls    rw1
  1495.                     ; doing intermediate transfer
  1496. itrw0:    moveq    #0,d1            ; assume moving 1 byte at a time
  1497.     btst.b    #0,ybuf+3(a6)        ; odd boundary?
  1498.     bne.s    itrw1            ; if so, assumption ok
  1499.     moveq    #2,d1            ; else move 1 long at a time
  1500.  
  1501. itrw1:    tst.l    frbbuf            ; is there a fast RAM buffer?
  1502.     bne.s    itrw2            ; if there is one, use it
  1503.                     ; else look for _FRB
  1504.     move.l    d1,-(sp)        ; save d1
  1505.     move.l    #frbbuf,-(sp)        ; pointer to fast RAM buffer
  1506.     move.l    #_FRB,-(sp)        ; looking for cookie _FRB
  1507.     bsr    _getcookie        ; 
  1508.     addq.w    #8,sp            ; clean up stack
  1509.     move.l    (sp)+,d1        ; restore d1
  1510.     tst.w    d0            ; found _FRB?
  1511.     bne.s    itrw2            ; if so, use it
  1512.                     ; else use dskbuf
  1513.     movea.l    _dskbufp,a1        ; a1 -> dskbuf
  1514.     cmpi.w    #2,d2            ; can only do 2 at a time tops
  1515.     bls.s    itrw3
  1516.     move.w    #2,d2
  1517.     bra.s    itrw3
  1518.  
  1519. itrw2:    movea.l    frbbuf,a1        ; use the Fast RAM Buffer
  1520.     cmpi.w    #RAMRSV,d2        ; can only do RAMRSV at a time tops
  1521.     bls.s    itrw3
  1522.     move.w    #RAMRSV,d2
  1523.  
  1524. itrw3:    btst.b    #0,yrw+1(a6)        ; is this a read?
  1525.     beq.s    rw1            ; if so, go fill buffer from disk
  1526.                     ; else fill buffer here
  1527.     move.l    a1,-(sp)        ; preserve a1 = dest
  1528.     movea.l    ybuf(a6),a2        ; a2 = source
  1529.     move.w    d2,d0            ; # sectors to be moved
  1530.     bsr    smove            ; move sectors from a2 to a1
  1531.     movea.l    (sp)+,a1        ; restore a1.l = dest
  1532.     bra.s    rw1            ; go do the r/w
  1533.  
  1534. scrw0:    cmpi.l    #MAXSCSECTS,d2        ; more than one SCSI DMAful?
  1535.     bls.s    scrw1            ; if not, ready to r/w
  1536.     move.l    #MAXSCSECTS,d2        ; r/w only one SCSI DMAful?
  1537.  
  1538. scrw1:    
  1539.  
  1540. .if    SCDMA                ; if doing SCSI DMA
  1541. .if    !SCFRDMA            ; if no SCSI DMA to fast RAM
  1542.     cmpi.b    #$01,ybuf(a6)        ; is destination buffer in fast RAM?
  1543.     beq    itrw0            ; if so, do intermediate transfer
  1544. .endif    ;!SCFRDMA
  1545.  
  1546.     cmpa.l    #A32D16L,a1        ; buf in SCSI non-accessible
  1547.     bcs.s    rw1            ;  memory?
  1548.     cmpa.l    #A32D16H,a1        ; if so, do intermediate transfer
  1549.     bls    itrw0            ; else, go ahead with the I/O
  1550.     cmpa.l    #VA24D16,a1
  1551.     bcs.s    rw1
  1552.     cmpa.l    #VA16D16,a1
  1553.     bls    itrw0
  1554. .endif    ;SCDMA
  1555.  
  1556.     bra.s    rw1
  1557.  
  1558. rw0:    movea.l    ybuf(a6),a1        ; a1 = buffer address for r/w
  1559. rw1:    move.w    _retries,retrycnt    ; setup retry counter
  1560.  
  1561.     btst.b    #2,yrw+1(a6)        ; are retries disabled?
  1562.     beq.s    rw2            ; no, act normally
  1563.     move.w    #0,retrycnt        ; yes, so set retrycnt to zero
  1564.  
  1565. rw2:    movem.l    d1-d2/a1,-(sp)        ; preserve d1, d2 and a1
  1566.     move.w    cpun,-(sp)        ; dev.w
  1567.     move.l    a1,-(sp)        ; buf.l
  1568.     move.w    d2,-(sp)        ; count.w
  1569.     move.l    yrecno(a6),-(sp)    ; sect.L
  1570.     cmpi.l    #MAXACSECTS,d2        ; more than hr/w can handle?
  1571.     bhi.s    rw4            ; if so, use extended call (SCSI only)
  1572.     btst.b    #0,yrw+1(a6)        ; read or write?
  1573.     bne.s    rw3            ; (write)
  1574.     bsr    _hread            ; read sectors
  1575.     bra.s    rw6
  1576. rw3:    bsr    _hwrite            ; write sectors
  1577.     bra.s    rw6
  1578. rw4:    btst.b    #0,yrw+1(a6)        ; read or write?
  1579.     bne.s    rw5            ; (write)
  1580.     bsr    _xtdread        ; read sectors
  1581.     bra.s    rw6
  1582. rw5:    bsr    _xtdwrt            ; write sectors
  1583. rw6:    adda    #12,sp            ; (cleanup stack)
  1584.     movem.l    (sp)+,d1-d2/a1        ; restore d1, d2 and a1
  1585.     tst.l    d0            ; errors?
  1586.     beq    rwf            ; no error --> successful
  1587.     bmi.s    rw9            ; timed out --> retry
  1588.  
  1589.     movem.l    d1-d2/a1,-(sp)        ; preserve d1, d2 and a1
  1590.     bsr    errcode            ; find error code
  1591.     movem.l    (sp)+,d1-d2/a1        ; restore d1, d2 and a1
  1592.  
  1593.     cmpi.b    #MDMCHGD,d0        ; media change detected?
  1594.     bne.s    rw7            ; if not, fine
  1595.                     ; else record media may be changed
  1596.     move.b    #1,d0            ; d0.b = 1 (may be changed)
  1597.     bsr    s_mc_xst        ; set mcflgs and xst flags for all dev
  1598.  
  1599.     btst.b    #1,yrw+1(a6)        ; ignore media change?
  1600.     bne    rw2            ; if so, retry operation
  1601.     move.l    #E_CHNG,d0        ; else return media change
  1602.     bra    rwr
  1603.     
  1604. rw7:    cmpi.b    #WRTPRTD,d0        ; write on write-protected media?
  1605.     bne.s    rw8            ; if not, fine
  1606.     move.l    #EWRPRO,d0        ; else return write-protection error
  1607.     bra.s    rwa
  1608.  
  1609. rw8:    cmpi.b    #DRVNRDY,d0        ; drive not ready?
  1610.     bne.s    rw9            ; if not, fine
  1611.     move.l    #EDRVNR,d0        ; else return drive not ready
  1612.     bra.s    rwa
  1613.  
  1614. rw9:    subq.w    #1,retrycnt        ; drop retry count and retry
  1615.     bpl    rw2
  1616.  
  1617.     move.l    #EREADF,d0        ; read error code
  1618.     btst.b    #0,yrw+1(a6)        ; is it a write?
  1619.     beq.s    rwa            ; (read)
  1620.     move.l    #EWRITF,d0        ; write error code
  1621.  
  1622. rwa:    btst.b    #3,yrw+1(a6)        ; is this a physical operation?
  1623.     bne    rwr            ; if so, exit
  1624.                     ; else call critical error handler
  1625.     movem.l    d1-d2/a1,-(sp)        ; preserve d1, d2 and a1
  1626.     move.w    ydev(a6),d1        ; d1 = drive number
  1627. rwe:    bsr    critic
  1628.     movem.l    (sp)+,d1-d2/a1        ; restore d1, d2 and a1
  1629.     cmpi.l    #CRITRETRY,d0        ; is it the magic RETRY code?
  1630.     beq    rw2            ; if yes, go retry
  1631.     bra.s    rwr            ; else, head home
  1632.  
  1633. rwf:    lea    rw0,a0            ; exec of next r/w starts at rw1
  1634.     cmpa.l    ybuf(a6),a1        ; was alternate buffer used?
  1635.     beq.s    rw10            ; if not, go on to next r/w
  1636.                     ; else take care of transfer
  1637.     lea    itrw3,a0        ; exec of next r/w starts at itrw3
  1638.     btst.b    #0,yrw+1(a6)        ; was it a write?
  1639.     bne.s    rw10            ; if it was, go on to next write
  1640.                     ; else move data to supplied buffer
  1641.     move.l    a1,-(sp)        ; save address of alternate buffer
  1642.     movea.l    a1,a2            ; a2 = address of alternate buffer
  1643.     movea.l    ybuf(a6),a1        ; a1 = address of supplied buffer
  1644.     move.w    d2,d0            ; d0 = # of sectors to move
  1645.     bsr    smove            ; move data from alt buf to sup buf
  1646.     move.l    (sp)+,a1        ; restore address of alternate buffer
  1647.  
  1648. rw10:    sub.l    d2,ycount(a6)        ; ycount(a6) = # sects left to be done
  1649.     beq.s    rwd            ; if no more left, done
  1650.                     ; else get ready for next r/w
  1651.     add.l    d2,yrecno(a6)        ; yrecno(a6) = next starting sector
  1652.     move.l    d2,d0            ; d0 = # bytes done
  1653.     asl.l    #8,d0            ;    = # sectors done * 512
  1654.     add.l    d0,d0            ; 
  1655.     add.l    d0,ybuf(a6)        ; buf += (sectors_done * sector size)
  1656.     cmp.l    ycount(a6),d2        ; amount to r/w > amount doable?
  1657.     bls.s    rw11            ; if so, r/w amount doable
  1658.     move.l    ycount(a6),d2        ; else r/w all of it
  1659. rw11:    jmp    (a0)            ; go on to next r/w
  1660.  
  1661. rwd:    moveq    #0,d0            ; got here with no errors!
  1662. rwr:    unlk    a6            ; head home
  1663.     rts
  1664.  
  1665.  
  1666. ;
  1667. ;+
  1668. ; Check for media change on hard disk
  1669. ; Synopsis:    _sasi_mediach(dev)
  1670. ;        WORD dev;        4(sp).w
  1671. ;
  1672. ; Returns:    0L - media definitely has not changed
  1673. ;        1L - media _may_ have changed
  1674. ;        2L - media definitely has changed
  1675. ;
  1676. ; Uses:        d0, d1, a0, a1
  1677. ;
  1678. ; Comments:
  1679. ; Apr-4-1989    ml.    Add in grace period between _sasi_mediach()s.
  1680. ;            If _sasi_mediach() was called less than 1 s
  1681. ;            (200 _hz_200 clock ticks) ago, and medium was 
  1682. ;            not changed then, assume medium still has not 
  1683. ;            changed.
  1684. ;-
  1685. _sasi_mediach:
  1686.     subq.w    #2,4(sp)        ; dev # excluding drv A and B
  1687.     move.w    4(sp),d1        ; d1 = current drive
  1688.     lea    mcflgs,a0        ; a0 = pointer to mcflgs
  1689.     moveq    #0,d0            ; d0 = mcflg for current drive
  1690.     move.b    (a0,d1.w),d0    
  1691.     tst.b    d0            ; has medium changed?
  1692.     bne.s    decided            ; if yes or maybe, return result
  1693.                     ; else verify that it has not
  1694.     move.l    lastmdctm,d2        ; time media change was last called
  1695.     cmp.l    _hz_200,d2        ; while (_hz_200 <= lastmdctm)
  1696.     bcc.s    decided            ;    assume medium not changed
  1697.  
  1698.     lea    pun,a1            ; ptr to beginning of pun table
  1699.     move.b    (a1,d1.w),cpun+1    ; cpun = pun current drive belongs to
  1700.  
  1701.     btst.b    #6,cpun+1        ; is pun removable?
  1702.     beq.s    notchngd        ; if not, medium has not changed
  1703.  
  1704.     move.w    cpun,-(sp)        ; physical unit number
  1705.     bsr    _untrdy            ; verify by doing test unit ready
  1706.     addq.l    #2,sp
  1707.     move.l    _hz_200,lastmdctm    ; update time for last _sasi_mediach()
  1708.     addi.l    #200,lastmdctm        ; 
  1709.     tst.w    d0            ; return good status?
  1710.     beq.s    notchngd        ; if yes, return medium not changed
  1711.     moveq    #1,d0            ; else return medium may have changed
  1712.     bsr    s_mc_xst        ; set mcflgs and xst flags to 1's
  1713.     bra.s    decided
  1714. notchngd:
  1715.     moveq    #0,d0            ; return medium has not changed
  1716. decided:
  1717.     rts
  1718.  
  1719.  
  1720. ;+
  1721. ; s_mc_xst - set mcflgs and drive existence flags 
  1722. ;         for drives belonging to the current
  1723. ;         physical unit to value passed
  1724. ;
  1725. ; Passed:    d0.b - value to set to
  1726. ;-
  1727. s_mc_xst:
  1728.     movem.l    d1-d2/a0-a2,-(sp) ; save registers
  1729.     lea    pun,a0        ; a0 -> pun table
  1730.     lea    mcflgs,a1    ; a1 -> mcflgs table
  1731.     lea    xst,a2        ; a2 -> drive existence table
  1732.     move.w    cpun,d1        ; d1 = current physical unit #
  1733.     moveq    #0,d2        ; d2 = logical drive #; index into tables
  1734. set0:    btst.b    #7,(a0,d2.w)    ; a valid logical drive?
  1735.     bne.s    setr        ; if not, done
  1736.     cmp.b    (a0,d2.w),d1    ; else, does it belong to this physical unit?
  1737.     bne.s    set1        ; if not, move on to next logical drive
  1738.     move.b    d0,(a1,d2.w)    ; else change its mcflg to value passed
  1739.     move.b    d0,(a2,d2.w)    ; and change its xst to value passed
  1740. set1:    addq.w    #1,d2        ; try next one in forward direction
  1741.     cmp.w    #MAXUNITS,d2    ; all units checked?
  1742.     blt.s    set0        ; if not, go on
  1743. setr:    movem.l    (sp)+,d1-d2/a0-a2 ; else restore registers
  1744.     rts            ; and return
  1745.  
  1746.  
  1747. ;
  1748. ;+
  1749. ; Resident Installer
  1750. ;-
  1751.     .globl    i_sasi6
  1752. i_sasi6:
  1753.     move.l    #(i_sasi1-i_sasi),tokeep ; at least keep this much
  1754.     cmpi.w    #512,maxssz    ; maxssz > 512 bytes?
  1755.     bls.s    nboot1        ; if not, don't need to replace GEMDOS buffers
  1756.                 ; else check if there is enough memory for
  1757. chkmem:    bsr    chklstmem    ;   new GEMDOS buffer lists
  1758.     tst.l    d0        ; enough?
  1759.     bpl.s    okbig        ; if so, build the list
  1760.     move.w    defbigsect,d0    ; d0 = minimum big sector
  1761.     cmp.w    maxssz,d0    ; is maxssz >= minimum big sector?
  1762.     bcc.s    regsect        ; if so, give up
  1763.     move.w    d0,maxssz    ; else try minimum big sector
  1764.     bra.s    chkmem
  1765. regsect:
  1766.     move.w    #512,maxssz    ; will not handle big sectors
  1767.     bra.s    nboot1
  1768.  
  1769. okbig:    move.l    d1,tokeep    ; update amount of memory to be kept
  1770.     lea    i_sasi1,a0    ; a0 -> beginning of new buffer lists
  1771.     moveq    #3,d1        ; d1 = count = 4 buffers - 1
  1772.     bsr    list_init    ; initialize the buffer list
  1773.     clr.l    (a0,d0.w)    ; cut 1 list of 4 buffers to 2 lists of 2
  1774.     move.l    a0,_bufl    ; _bufl[0] -> 1st new buffer list
  1775.     add.l    d0,d0        ; d0 = offset to beginning of 2nd buffer list
  1776.     adda.l    d0,a0        ; a0 = head of 2nd buffer list
  1777.     move.l  a0,_bufl+4    ; _bufl[1] -> 2nd new buffer list
  1778.  
  1779. nboot1:    bsr    pool_install    ; attempt to install more OS pool
  1780.     add.l    d0,tokeep    ; update amount of memory to be kept
  1781.  
  1782. ;    clr.l    frbbuf        ; assume no _FRB
  1783. ;    move.l    #frbbuf,-(sp)    ; pointer to fast RAM buffer
  1784. ;    move.l    #$5f465242,-(sp)    ; cookie "_FRB"
  1785. ;    bsr    _getcookie    ; try to find _FRB in cookie jar
  1786. ;    addq.w    #8,sp        ; clean up stack
  1787.  
  1788.     move.l    _hz_200,lastmdctm    ; initialize media change time
  1789.     tst.w    bootloaded    ; if bootloaded, then already in super mode
  1790.     bne.s    nboot2        ; (already there)
  1791.     move.l    savssp,-(sp)    ; become a mild mannered user process
  1792.     move.w    #$20,-(sp)    ; Super(savssp)
  1793.     trap    #1
  1794.     addq.w    #6,sp
  1795.  
  1796. ;+
  1797. ; Terminate and stay resident;
  1798. ; installed driver under GEMDOS.
  1799. ;-
  1800.     move.l    tokeep,d0    ; compute value for Ptermres()
  1801.     add.l    #$0100,d0    ; for basepage
  1802.     move.l    d0,-(sp)    ; save D0
  1803.     pea    msg_nbl(pc)    ; print announcement
  1804.     move.w    #9,-(sp)
  1805.     trap    #1
  1806.     addq.l    #6,sp
  1807.     move.l    (sp)+,d0
  1808.     move.w    #0,-(sp)    ; exit code
  1809.     move.l    d0,-(sp)
  1810.     move.w    #$31,-(sp)    ; terminate and stay resident
  1811.     trap    #1        ; should never come back...
  1812.     illegal
  1813.  
  1814.  
  1815. ;+
  1816. ;  Return to TOS ROMs
  1817. ;    - set default boot device to C:
  1818. ;    - Print silly message
  1819. ;    - Mshrink() memory that was alloc'd to us
  1820. ;    - set magic# in D7 for TOS ROMs
  1821. ;    - RTS back to ROMs
  1822. ;-
  1823. nboot2:    move.l    tokeep,d0    ; compute value for Mshrink
  1824.     add.l    #$1c,d0        ; for file header
  1825.     move.l    d0,-(sp)    ; save D0
  1826.     pea    msg_bl(pc)    ; print announcement
  1827.     move.w    #9,-(sp)
  1828.     trap    #1
  1829.     addq.l    #6,sp        ; clean up stack
  1830.  
  1831.     move.w    d4,d1        ; physical unit # in d4.w?
  1832.     bpl.s    bd0        ; if so, good
  1833.                 ; else it's in hi 3 bits of d7.b
  1834.     move.b    d7,d1        ; d1.b = physical unit # boot loaded from
  1835.     lsr.b    #5,d1        ;      = xxx00000 >> 5
  1836. bd0:    lea    pun,a0        ; a0 -> pun table
  1837.     moveq    #0,d2        ; d2 = boot dev
  1838. bd1:    move.b    (a0,d2.w),d0    ; d0.b = unit #
  1839.     andi.b    #$0f,d0        ; mask out flags
  1840.     cmp.b    d0,d1        ; d2 belongs to physical unit booted from?
  1841.     beq.s    bd2        ; if yes, set (d2) as boot device
  1842.     addq.w    #1,d2        ; else try next logical unit
  1843.     bra.s    bd1
  1844. bd2:    addq.w    #2,d2        ; offset for drive A and B
  1845.     move.w    d2,_bootdev    ; set default boot device to (d2)
  1846.  
  1847.     move.l    baseaddr,-(sp)
  1848.     clr.w    -(sp)
  1849.     move.w    #$4a,-(sp)    ; Mshrink(...)
  1850.     trap    #1
  1851.     adda    #12,sp        ; (cleanup stack)
  1852.  
  1853.     move.w    _bootdev,-(sp)    ; set boot dev as default drive
  1854.     move.w    #$e,-(sp)    ; Dsetdrv(_bootdev)
  1855.     trap    #1
  1856.     addq.w    #4,sp        ; cleanup stack
  1857.  
  1858.     move.l    #rootpath,-(sp)    ; set root as current directory
  1859.     move.w    #$3b,-(sp)    ; Dsetpath('\')
  1860.     trap    #1
  1861.     addq.w    #6,sp        ; cleanup stack
  1862. ;
  1863. ;    move.l    _sysbase,a0    ; get the system header address
  1864. ;    move.l    $18(a0),d0    ; d0.l = MMDDYYYY of ROM date
  1865. ;    swap    d0        ; d0.l = YYYYMMDD of ROM date
  1866. ;    cmp.l    #CHKDATE,d0    ; does this version of ROM need bootstop?
  1867. ;    bcs.s    stopall        ; yup, if OS is built before 4/22/87
  1868. ;    move.b    puns+1,d7    ; else prevent processed units from booting
  1869. ;    subq.b    #1,d7        ; unit # = # of units - 1
  1870. ;    lsl.b    #5,d7
  1871. ;    rts            ; return to TOS ROMs
  1872. ;
  1873. ; Stop ANY subsequent boot after the hard disk boot -- FOR NOW!!
  1874. ;
  1875.  
  1876. stopall:
  1877.     move.b    #$100-$20,d7    ; prevent any other unit from booting
  1878.     rts            ; return to TOS ROMs
  1879.  
  1880. rootpath:
  1881.     dc.b    '\\',0
  1882. msg_bl:
  1883.     dc.b    'BOOTLOADED',13,10,0
  1884. msg_nbl:
  1885.     dc.b    'NOT Bootloaded',13,10,0
  1886. .even
  1887.  
  1888.  
  1889. ;+
  1890. ; list_init - Initialize a GEMDOS buffer list (BCBs are contiguous)
  1891. ;
  1892. ; Passed:
  1893. ;     a0.l = head of buffer list            (not changed)
  1894. ;    d0.l = size of each BCB (including data block)    (not changed)
  1895. ;    d1.w = count
  1896. ;         = number of buffers to be installed to the list - 1
  1897. ;
  1898. ; Uses:
  1899. ;    d1, a1
  1900. ;-
  1901. list_init:
  1902.     move.l    a0,-(sp)    ; save head of buffer list
  1903. lin0:    movea.l    a0,a1        ; a1 -> next BCB
  1904.     adda.l    d0,a1        ;    -> curr BCB + size of BCB
  1905.     move.l    a1,(a0)        ; b_link -> next BCB
  1906.     move.w    #-1,4(a0)    ; b_neg1 = -1
  1907.     adda.w    #BCBLEN,a0    ; a0 -> BCB data block
  1908.     move.l    a0,-4(a0)    ; b_bufr -> b_space
  1909.     movea.l    a1,a0
  1910.     dbra    d1,lin0
  1911.     suba.l    d0,a0        ; a0 -> last BCB
  1912.     clr.l    (a0)        ; lastBCB.b_link = NULL
  1913.     move.l    (sp)+,a0    ; restore head of buffer list
  1914.     rts
  1915.  
  1916.  
  1917. ;+
  1918. ; chklstmem - check if enough memory is allocated to replace GEMDOS
  1919. ;        buffer lists
  1920. ;
  1921. ; Returns:
  1922. ;    d0.l = size of each BCB (including data block)
  1923. ;         or -1 if not enough memory is allocated
  1924. ;    d1.l = new amount of memory to be kept if enough is allocated
  1925. ;
  1926. ; Uses:
  1927. ;    d0, d1
  1928. ;-
  1929. chklstmem:
  1930.     moveq    #BCBLEN,d0    ; d0.l = size of each BCB (inc. data block)
  1931.     add.w    maxssz,d0    ;      = BCB header len + data block size
  1932.     move.l    d0,d1        ; d1.l = d0.l * 4 
  1933.     lsl.l    #2,d1        ;      = total size of buffer lists
  1934.     add.l    tokeep,d1    ; d1.l = size needed
  1935.     cmp.l    memalloc,d1    ; enough memory allocated?
  1936.     bls.s    chk0        ; if so return
  1937.     moveq    #-1,d0        ; else return error
  1938. chk0:    rts
  1939.  
  1940.  
  1941. ;
  1942. ;+
  1943. ; critic - call up the critical error handler.
  1944. ;
  1945. ; Passed:
  1946. ;    d0.w = error code
  1947. ;    d1.w = drive # excluding A: and B:
  1948. ;
  1949. ; Uses:
  1950. ;    d0, d1, a0
  1951. ;
  1952. ; Returns:
  1953. ;    d0.l = whatever returned by the critical handler
  1954. ;        (magic RETRY code or something)
  1955. ;-
  1956. critic:    addq.w    #2,d1            ; drive # including A: and B:
  1957.     move.w    d1,-(sp)        ; drive #
  1958.     move.w    d0,-(sp)        ; error code
  1959.     movea.l    etv_critic,a0        ; a0 = address of error handler
  1960.     jsr    (a0)            ; critic_handler(error, drive)
  1961.     addq.l    #4,sp            ; clean up stack
  1962.     rts                ; return
  1963.  
  1964.  
  1965. ;+
  1966. ; errcode - find error code for previous Check Condition Status
  1967. ;
  1968. ; Assumed:
  1969. ;    cpun = current physical unit number
  1970. ;
  1971. ; Returns:
  1972. ;    d0.b = error code    (aka additional sense code)
  1973. ;
  1974. ; Sep-13-1989    ml.    For non-extended request sense, ask for 0 byte.
  1975. ;            (0 is default to return 4 bytes.)
  1976. ;-
  1977.     .globl    errcode
  1978. errcode:
  1979.     moveq    #22,d1            ; assume requesting extended sense
  1980.     move.w    cpun,d0            ; d0 = physical unit number
  1981.     btst    #3,d0            ; a SCSI unit?
  1982.     bne.s    err0            ; if so, ready to request
  1983.     andi.w    #07,d0            ; else mask off other flags
  1984.     btst.b    d0,embscsi        ; an embedded SCSI unit using ACSI?
  1985.     bne.s    err0            ; if so, request extended sense
  1986.     moveq    #0,d1            ; else request non-extended sense
  1987. err0:    lea    sendata,a0        ; a0 -> sense data buffer
  1988.     movem.l    d1/a0,-(sp)        ; save data len and buffer address
  1989.     move.l    a0,-(sp)        ; sense data buffer
  1990.     move.w    d1,-(sp)        ; data length (in bytes)
  1991.     move.w    d0,-(sp)        ; physical unit number
  1992.     bsr    _rqsense        ; find out error code
  1993.     addq.l    #8,sp            ; clean up stack
  1994.     movem.l    (sp)+,d1/a0        ; restore d1 and a0
  1995.     tst.w    d0            ; successful?
  1996.     beq.s    err1            ; if not, return
  1997.     moveq    #-1,d0            ; error occurred
  1998.     rts
  1999. err1:    cmpi.w    #4,d1            ; extended or non-extended?
  2000.     bgt.s    err2            ; if extended, go get code
  2001.     move.b    (a0),d0            ; else byte 0 = error code
  2002.     andi.b    #$7f,d0            ; mask off valid bit
  2003.     rts
  2004. err2:    move.b    12(a0),d0        ; else byte 12 = error code
  2005.     rts
  2006.  
  2007.  
  2008. ;
  2009. ;+
  2010. ; OS Pool Expansion
  2011. ;-
  2012.  
  2013. .if ospool
  2014. ;+
  2015. ;  Wire more pool into various ROM releases.
  2016. ;
  2017. ;    Passed:    nothing
  2018. ;    Returns:    D0 = #bytes extra used
  2019. ;-
  2020. pool_install:
  2021.     move.l    _sysbase,a3        ; a3 -> base of OS
  2022.  
  2023. ; make sure we're in ROM,
  2024. ; then get address of RAM location to patch:
  2025.  
  2026.     cmp.l    #$800000,a3        ; better be ROM
  2027.     blt    notrom
  2028.     lea    pool_tab(pc),a0        ; a0 -> table to match
  2029. pi_lp:    move.l    (a0)+,d1        ; d1 = date to match
  2030.     beq    badrom            ; (forget it, end of list)
  2031.     move.l    (a0)+,a2        ; a2 -> _root address for that date
  2032.     cmp.l    $18(a3),d1        ; match dates?
  2033.     bne.s    pi_lp            ; (no -- try again)
  2034.  
  2035.     move.w    numchunks,d0        ; d0 = amount of BSS to be used
  2036.     mulu    #chunksiz,d0        ;    = # chunks * size of a chunk
  2037.     move.l    d0,d1            ; d1 = total memory needed
  2038.     add.l    tokeep,d1        ;    = already keeping + extra OS pool
  2039.     cmp.l    memalloc,d1        ; enough is allocated?
  2040.     bgt.s    bdrom2            ; if not, don't add any
  2041.                     ; else install more OS pool
  2042.     movea.l    #i_sasi+2,a0        ; a0 -> base of first buffer
  2043.     adda.l    tokeep,a0        ;    = start of file + already keeping
  2044.     move.l    a0,-(sp)        ; save base of first buffer
  2045.     move.w    numchunks,d1        ; d0 = count-1
  2046.     subq.w    #1,d1
  2047. pin_1:    lea    chunksiz(a0),a1        ; a1 -> next buffer
  2048.     move.l    a1,(a0)            ; buffer -> next one
  2049.     move.w    #chunkno,-2(a0)        ; install chunksiz
  2050.     move.l    a1,a0            ; a0 -> next buffer
  2051.     dbra    d1,pin_1        ; (do some more)
  2052.  
  2053.     sub.w    #chunksiz,a0        ; a0 -> last block
  2054.     move.l    chunkno*4(a2),(a0)    ; last block -> first in root
  2055.     move.l    (sp)+,chunkno*4(a2)     ; root -> first of ours
  2056.     rts                ; return OK
  2057.  
  2058. ;+
  2059. ;  Print warning messages
  2060. ;  about bogus versions of the
  2061. ;  operating system.  Assume that
  2062. ;  every OS past 1-May-1986 has the
  2063. ;  pool fix installed.
  2064. ;
  2065. ;-
  2066. ok_date    =    %0000110010100001    ; 1-May-1986
  2067. notrom:    lea    m_notrom(pc),a0        ; ram-based system (5/29!)
  2068.     bra.s    bdrom1
  2069. badrom:    lea    m_badrom(pc),a0        ; illegal ROM system
  2070. bdrom1:    cmp.w    #ok_date,$1e(a3)    ; if ok_date <= os_dosdate(a3) 
  2071.     bcc    bdrom2            ; then don't print anything
  2072.  
  2073.     move.l    a0,-(sp)        ; print nasty message
  2074.     move.w    #9,-(sp)
  2075.     trap    #1
  2076.     addq.l    #6,sp
  2077.  
  2078. ; print msg and wait for RETURN
  2079.     pea    keymsg(pc)
  2080.     move.w    #9,-(sp)
  2081.     trap    #1
  2082.     addq.l    #6,sp
  2083.  
  2084. bdrom3:    move.w    #2,-(sp)        ; wait for [RETURN]
  2085.     move.w    #2,-(sp)
  2086.     trap    #13
  2087.     addq.l    #4,sp
  2088.     cmp.w    #13,d0
  2089.     bne    bdrom3
  2090.  
  2091. bdrom2:    moveq    #0,d0            ; 0 extra bytes used
  2092.     rts
  2093.  
  2094. keymsg:    dc.b    'Hard disk driver not loaded; hit RETURN',13,10
  2095.     dc.b    'key to continue:',13,10
  2096.     dc.b    0
  2097.  
  2098. m_notrom:
  2099.     dc.b    '*** WARNING ***',13,10,7
  2100.     dc.b    'This hard disk driver may not work with',13,10,7
  2101.     dc.b    'a disk-based version of TOS; files on',13,10,7
  2102.     dc.b    'your hard disk may be damaged.',13,10,7
  2103.     dc.b    13,10,7
  2104.     dc.b    0
  2105.  
  2106. m_badrom:
  2107.     dc.b    '*** WARNING ***',13,10,7
  2108.     dc.b    'You are using an unofficial ROM release',13,10,7
  2109.     dc.b    'of the operating system.  This driver',13,10,7
  2110.     dc.b    'may not work correctly with it.  Files',13,10,7
  2111.     dc.b    'on your hard disk may be damaged.',13,10,7
  2112.     dc.b    13,10,7
  2113.     dc.b    0
  2114.     even
  2115.  
  2116.  
  2117. ;+
  2118. ;  Table of ROM release dates / _root addresses
  2119. ;  update these for new ROM releases that need the patch.
  2120. ;
  2121. ;-
  2122. pool_tab:
  2123.     dc.l    $11201985,$56fa        ; USA and UK, 20-Nov-1985
  2124.     dc.l    $02061986,$56fa        ; Germany, 6-Feb-1986
  2125.     dc.l    $04241986,$56fa        ; France, 24-Apr-1986
  2126.     dc.l    0            ; end of list
  2127.  
  2128. .endif
  2129.  
  2130.  
  2131.